home *** CD-ROM | disk | FTP | other *** search
- {$DEFINE StackCheck}
- {$DEFINE test}
-
- {$IFDEF test}
- {$A+,B-,D+,E-,F-,G-,I+,L+,N-,O-,R+,S+,V+,X-}
- {$M 16384,0,655360}
- {$ELSE}
- {$A+,B-,D+,E-,F-,G-,I-,L+,N-,O-,R-,S-,V-,X-}
- {$M 16384,150000,655360}
- {$ENDIF}
-
- PROGRAM PCX_to_COD_and_PIC_converter;
-
- USES Dos,Graph,crt,Eingaben,Dateien;
- const
- MausMinX=0; {Koordinatenbereich für Maus}
- MausMinY=0;
- MausMaxX:INTEGER=0;
- MausMaxY:INTEGER=0;
- MausMaxX_mul2:INTEGER=0;
- MausMaxY_mul2:INTEGER=0;
-
- SVGA320x200x256 = 0; (* 320x200x256 Standard VGA *)
- SVGA640x400x256 = 1; (* 640x400x256 Svga *)
- SVGA640x480x256 = 2; (* 640x480x256 Svga *)
- SVGA800x600x256 = 3; (* 800x600x256 Svga *)
- SVGA1024x768x256 = 4; (* 1024x768x256 Svga *)
-
- CONST EventNone=0; {gar nix}
- EventError=1; {Fehler }
- EventQuit=2; {Programm vielleicht beenden}
- EventHelp=9; {Hilfe}
- EventMouseMoved=17; {Maus wurde bewegt}
- EventEndProgram=41; {Programm tatsächlich beenden}
- EventSpeichern=100; {ausgewählten Grafikbereich abspeichern}
-
- {---------Menu-Felder---------}
-
- TYPE DrawBox=PROCEDURE;
- box=RECORD {Datentyp für ein Menufeld:}
- x1,y1, {obere linke Boxecke}
- x2,y2:WORD; {untere rechte Ecke }
- Name1,Name2:STRING[8]; {Beschriftung 1.+2.Zeile}
- Show :DrawBox; {Routine zum anzeigen des Icons}
- Event:BYTE; {zurückzugebender Wert}
- Click:BOOLEAN; {muß Maus geclickt werden für Event?}
- Paint:BOOLEAN; {Flag, ob Box zu zeichnen ist}
- END;
- boxes=ARRAY[1..3] OF box; {alle Menufelder zusammen}
-
- ButtonStringTyp=STRING[8]; {Meldung in Clickboxen}
-
- PROCEDURE Dummy; FAR; BEGIN END;
-
- CONST Menu:boxes=(
-
- {gesamter Mausbereich kann auch als "Menubox" realisiert werden:}
- (x1:MausMinX; y1:MausMinY;
- x2:0 {MausMaxX}; y2:0 {MausMaxY};
- Name1:'';Name2:'';
- Show :Dummy;
- Event:EventMouseMoved;
- Click:FALSE; {kein Anclicken nötig}
- Paint:FALSE), {...wird aber nicht gezeichnet}
-
- {Sentinelwert, da x1>x2!}
- (x1:1; y1:0; x2:0; y2:0;
- Name1:'';Name2:'';
- Show :Dummy;
- Event:EventNone;
- Click:TRUE;
- Paint:TRUE),
-
- {Noch einer als Füller, x1>x2!}
- (x1:1; y1:0; x2:0; y2:0;
- Name1:'';Name2:'';
- Show :Dummy;
- Event:EventNone;
- Click:TRUE;
- Paint:TRUE)
- );
-
- VAR event:BYTE;
- CRTAddress, {Adresse des CRT-Ports, $3B4/$3D4 fuer monochrom/Farbe}
- StatusReg:WORD; {dto., fuer Statusregister, $3BA/$3DA}
- Shift:BOOLEAN; {gibt wieder, ob während Auswertung Shift gedrückt war}
- BestWhite, {Beste Näherungen der angeg. Farben}
- BestBlack,
- BestCyan,
- BestLightGray,
- BestDarkGray:BYTE;
- MeldungX,MeldungY:INTEGER;
-
- {-------------------- Ziffernausgabe ------------------}
- TYPE Ziffer=ARRAY[0..6,0..7] OF BYTE;
- ToldArea=ARRAY[0..9*8,0..7] OF BYTE;
- CONST Ziffern:ARRAY['0'..'9'] OF Ziffer=
- (
- ((0,1,1,1,1,1,0,0),
- (1,1,0,0,0,1,1,0),
- (1,1,0,0,1,1,1,0),
- (1,1,0,1,1,1,1,0),
- (1,1,1,1,0,1,1,0),
- (1,1,1,0,0,1,1,0),
- (0,1,1,1,1,1,0,0)),
-
- ((0,0,1,1,0,0,0,0),
- (0,1,1,1,0,0,0,0),
- (0,0,1,1,0,0,0,0),
- (0,0,1,1,0,0,0,0),
- (0,0,1,1,0,0,0,0),
- (0,0,1,1,0,0,0,0),
- (1,1,1,1,1,1,0,0)),
-
- ((0,1,1,1,1,0,0,0),
- (1,1,0,0,1,1,0,0),
- (0,0,0,0,1,1,0,0),
- (0,0,1,1,1,0,0,0),
- (0,1,1,0,0,0,0,0),
- (1,1,0,0,1,1,0,0),
- (1,1,1,1,1,1,0,0)),
-
- ((0,1,1,1,1,0,0,0),
- (1,1,0,0,1,1,0,0),
- (0,0,0,0,1,1,0,0),
- (0,0,1,1,1,0,0,0),
- (0,0,0,0,1,1,0,0),
- (1,1,0,0,1,1,0,0),
- (0,1,1,1,1,0,0,0)),
-
- ((0,0,0,1,1,1,0,0),
- (0,0,1,1,1,1,0,0),
- (0,1,1,0,1,1,0,0),
- (1,1,0,0,1,1,0,0),
- (1,1,1,1,1,1,1,0),
- (0,0,0,0,1,1,0,0),
- (0,0,0,1,1,1,1,0)),
-
- ((1,1,1,1,1,1,0,0),
- (1,1,0,0,0,0,0,0),
- (1,1,1,1,1,0,0,0),
- (0,0,0,0,1,1,0,0),
- (0,0,0,0,1,1,0,0),
- (1,1,0,0,1,1,0,0),
- (0,1,1,1,1,0,0,0)),
-
- ((0,0,1,1,1,0,0,0),
- (0,1,1,0,0,0,0,0),
- (1,1,0,0,0,0,0,0),
- (1,1,1,1,1,0,0,0),
- (1,1,0,0,1,1,0,0),
- (1,1,0,0,1,1,0,0),
- (0,1,1,1,1,0,0,0)),
-
- ((1,1,1,1,1,1,0,0),
- (1,1,0,0,1,1,0,0),
- (0,0,0,0,1,1,0,0),
- (0,0,0,1,1,0,0,0),
- (0,0,1,1,0,0,0,0),
- (0,0,1,1,0,0,0,0),
- (0,0,1,1,0,0,0,0)),
-
- ((0,1,1,1,1,0,0,0),
- (1,1,0,0,1,1,0,0),
- (1,1,0,0,1,1,0,0),
- (0,1,1,1,1,0,0,0),
- (1,1,0,0,1,1,0,0),
- (1,1,0,0,1,1,0,0),
- (0,1,1,1,1,0,0,0)),
-
- ((0,1,1,1,1,0,0,0),
- (1,1,0,0,1,1,0,0),
- (1,1,0,0,1,1,0,0),
- (0,1,1,1,1,1,0,0),
- (0,0,0,0,1,1,0,0),
- (0,0,0,1,1,0,0,0),
- (0,1,1,1,0,0,0,0))
- );
-
- FUNCTION min(a,b:INTEGER):INTEGER;
- BEGIN
- IF a<=b THEN min:=a ELSE min:=b
- END;
-
- FUNCTION max(a,b:INTEGER):INTEGER;
- BEGIN
- IF a>=b THEN max:=a ELSE max:=b
- END;
-
- FUNCTION min3(a,b,c:INTEGER):INTEGER;
- BEGIN
- min3:=min(a,min(b,c))
- END;
-
- FUNCTION max3(a,b,c:INTEGER):INTEGER;
- BEGIN
- max3:=max(a,max(b,c))
- END;
-
- PROCEDURE PrintXY(x,y,a,b:INTEGER; VAR oldP:ToldArea);
- VAR n,i,j:INTEGER;
- s:STRING[8];
- BEGIN
- FOR i:=Max(0,x) TO Min(x+9*8-1,GetMaxX) DO
- FOR j:=Max(0,y) TO Min(y+7,GetMaxY) DO
- oldP[i-x,j-y]:=GetPixel(i,j);
-
- Str(a,s);
- FOR n:=1 TO Length(s) DO
- FOR j:=0 TO 6 DO
- BEGIN
- FOR i:=0 TO 7 DO
- IF (Ziffern[s[n]][j,i]=1)
- THEN PutPixel(x+i +Pred(n) SHL 3,y+j,BestWhite)
- END;
-
- INC(x,Length(s) SHL 3 +4);
- Str(b,s);
- FOR n:=1 TO Length(s) DO
- FOR j:=0 TO 6 DO
- BEGIN
- FOR i:=0 TO 7 DO
- IF (Ziffern[s[n]][j,i]=1)
- THEN PutPixel(x+i +Pred(n) SHL 3,y+j,BestWhite)
- END;
- END;
-
- {----------Maus-Routinen----------}
- CONST MouseMoved=1;
- LeftButtonPressed=2;
- LeftButtonReleased=4;
- RightButtonPressed=8;
- RightButtonReleased=16;
- SuppressMouse:BOOLEAN=FALSE;
- VAR Aufrufmaske,Maustasten:WORD;
- MausX,MausY,MausXalt,MausYalt:INTEGER;
- mouseX2,mouseY2:INTEGER; {interne Mauskoordinaten}
- oldMouse:RECORD
- BoxLeft,BoxRight,BoxTop,BoxBottom :ARRAY[0..1023] OF BYTE;
- {Speicher für Windowbox}
- oldX,oldY:WORD; {alte Mauskoordinaten}
- breite,hoehe:WORD; {des Fensters}
- oldP:ToldArea;
- END;
- MouseUpdate:BOOLEAN;
- LeftButton,RightButton:BOOLEAN;
- regs:REGISTERS;
-
-
- FUNCTION MouseEvent(VAR menu):BYTE;
- { in: MausX,MausY = aktuelle Mausposition}
- { LeftButton, RightButton = TRUE, wenn Mausbutton gedrückt}
- { Shift = TRUE, falls Shifttaste während des Mausclicks gedrückt }
- { worden ist}
- { menu = Array vom Typ "boxes", das die Menuboxkoordinaten enthält}
- { EventNone = Rückgabewert, falls Maus in keinem der Felder steht }
- {out: Der Index desjenigen "menu"-Eintrages, in dem die Maus steht; }
- { sollte dies keiner sein, so wird "EventNone"=0 zurückgegeben }
- {rem: Das Ende der Menueinträge muß durch einen Eintrag mit x1>x2 an- }
- { gegeben werden!}
- VAR i:BYTE;
- a:boxes ABSOLUTE menu;
- BEGIN
- i:=1;
- WHILE (a[i].x1<=a[i].x2) DO
- BEGIN
- WITH a[i] DO
- IF (x1<=MausX) AND (MausX<=x2) AND (y1<=MausY) AND (MausY<=y2)
- AND ( (NOT click) OR (LeftButton OR RightButton) )
- THEN BEGIN
- MouseEvent:=Event;
- exit
- END
- ELSE INC(i)
- END;
- MouseEvent:=EventNone;
- END;
-
- PROCEDURE DrawMaus;
- { in: MausX,MausY = Koordinaten für Mauscursor}
- { MausXalt,MausYalt = Koord. des vorherigen Aufrufs}
- { oldMouse.Box* = Platz für Grafikausschnitt unter Mauscursor}
- {out: oldMouse.* = gerettete Grafikdaten}
- {rem: Der Speicherplatz MouseMem^ muß bereits reserviert worden sein }
- { Obwohl die Routine "Cursor" nicht verändert, wird als VAR-Para- }
- { meter übergeben, da dann nur ein Zeiger übergeben wird!}
- VAR i,oldX2,oldY2:WORD;
- diff:INTEGER;
- BEGIN
- WITH oldMouse DO
- BEGIN
- oldx:=MausX; oldY:=MausY;
- diff:=GetMaxX-(MausX+breite-1);
- IF diff<0 THEN inc(breite,diff);
- diff:=GetMaxY-(MausY+hoehe-1);
- IF diff<0 THEN inc(hoehe,diff);
- IF breite<1 THEN breite:=1;
- IF hoehe<1 THEN hoehe:=1;
- PrintXY(oldX+1,oldY+1,breite,hoehe,oldP);
-
- oldx2:=MausX+breite-1; oldY2:=MausY+hoehe-1;
- FOR i:=oldX TO oldX2 DO
- BEGIN
- BoxTop[i]:=GetPixel(i,oldY);
- BoxBottom[i]:=GetPixel(i,oldY2);
- IF Odd(i)
- THEN BEGIN
- PutPixel(i,oldY,BestWhite);
- PutPixel(i,oldY2,BestWhite)
- END
- ELSE BEGIN
- PutPixel(i,oldY,BestBlack);
- PutPixel(i,oldY2,BestBlack)
- END
- END;
- FOR i:=oldY+1 TO oldY2-1 DO
- BEGIN
- BoxLeft[i]:=GetPixel(oldX,i);
- BoxRight[i]:=GetPixel(oldX2,i);
- IF Odd(i)
- THEN BEGIN
- PutPixel(oldX,i,BestWhite);
- PutPixel(oldX2,i,BestWhite)
- END
- ELSE BEGIN
- PutPixel(oldX,i,BestBlack);
- PutPixel(oldX2,i,BestBlack)
- END
- END;
-
- END;
- END;
-
- PROCEDURE UnDrawMaus;
- { in: oldMouse.* = zu restaurierende Grafikdaten}
- VAR i,j,oldX2,oldY2:WORD;
- BEGIN
- WITH oldMouse DO
- BEGIN
- oldX2:=oldX+breite-1; oldY2:=oldY+hoehe-1;
- FOR i:=oldX TO oldX2 DO
- BEGIN
- PutPixel(i,oldY,BoxTop[i]);
- PutPixel(i,oldY2,BoxBottom[i])
- END;
- FOR i:=oldY+1 TO oldY2-1 DO
- BEGIN
- PutPixel(oldX,i,BoxLeft[i]);
- PutPixel(oldX2,i,BoxRight[i])
- END;
- FOR i:=Max(0,oldX+1) TO Min(oldX+1+9*8-1,GetMaxX) DO
- FOR j:=Max(0,oldY+1) TO Min(oldY+1+7,GetMaxY) DO
- PutPixel(i,j,oldP[i-(oldX+1),j-(oldY+1)]);
- END;
- END;
-
- FUNCTION MouseInstalled : Boolean;
- { in: - }
- {out: TRUE|FALSE für: Maus gefunden/nicht gefunden}
- VAR INT33h:POINTER;
- BEGIN
- GetIntVec($33,INT33h);
- IF (BYTE(INT33h^)=$CF) OR (LONGINT(INT33h)=0)
- THEN MouseInstalled:=FALSE {nur IRET oder Nullpointer}
- ELSE BEGIN {INT33h führt nicht ins Nirwana, trau dich!}
- WRITELN(10);
- (* regs.ax := 0; {Ja hallo, gibt's hier ne Maus im System?}
- Intr($33,regs);
- MouseInstalled:=(regs.ax=$FFFF); *)
- ASM
- PUSHF
- CLI
- PUSH BX
- PUSH CX
- PUSH DX
- PUSH SI
- PUSH DI
- PUSH BP
- PUSH ES
- PUSH DS
-
- mov ax,0
- int 33h
-
- POP DS
- POP ES
- POP BP
- POP DI
- POP SI
- POP DX
- POP CX
- POP BX
- STI
- POPF
-
- CMP AX,$FFFF
- JNE @noMouse
- MOV @Result,TRUE
- JMP @done
- @noMouse:
- MOV @Result,FALSE
- @done:
- END;
- WRITELN(9);
- END;
- END;
-
- PROCEDURE DisableMouse;
- inline($B0/<BYTE(TRUE)/ {MOV AL,TRUE}
- $A2/SuppressMouse); {MOV SuppressMouse,AL}
-
- PROCEDURE EnableMouse;
- inline($B0/<BYTE(FALSE)/ {MOV AL,FALSE}
- $A2/SuppressMouse); {MOV SuppressMouse,AL}
-
- PROCEDURE ClearMouse;
- BEGIN
- MouseUpdate:=FALSE; LeftButton:=FALSE; RightButton:=FALSE;
- EnableMouse;
- END;
-
- {$S-}
- PROCEDURE MouseCallBack; FAR; ASSEMBLER;
- { in: mouseX2,mouseY2 = alte Mauskoordinaten}
- { SuppressMouse = TRUE falls Mausereignis ignoriert werden soll}
- { MausMinX,MausMinY = minimal zulässige Mauskoordinaten}
- { MausMaxX,MausMaxY = maximal zulässige Mauskoordinaten}
- {out: Falls SuppressMouse=FALSE war, wurden folgende Variablen neugesetzt:}
- { MouseUpdate = TRUE}
- { MPressed = TRUE, falls linker Button gedrückt}
- { Shift = TRUE, falls eine der Shifttasten gedrückt wurde}
- { MausX,MausY = aktuelle Mauskoordinaten}
- { SuppressMouse = TRUE}
- {rem: Diese Prozedur entspricht einer Interrupt-Service-Routine, die}
- { immer dann aufgerufen wird, wenn eine der bei ihrer Initialisierung}
- { angegebenen Aufrufbedingungen erfüllt ist}
- { MouseUpdate = TRUE impliziert SuppressMouse:=TRUE, d.h.: die weitere}
- { Aktualisierung von Mausdaten ist solange gesperrt, bis die alten }
- { verarbeitet wurden und die Maus mit "EnableMouse()" wieder freige- }
- { geben wird!}
- ASM
- pushf
- push ax
- push bx
- push cx
- push dx
- push si
- push di
- push bp
- push ds
- push es
- mov bp,SEG @DATA
- mov DS,bp
-
- CMP SuppressMouse,TRUE {soll Maus überhaupt behandelt werden?}
- JE @quit
-
- MOV AufrufMaske,AX
- MOV MausTasten,BX
- MOV SI,MausX
- MOV MausXalt,SI
- MOV MausX,CX
- MOV SI,MausY
- MOV MausYalt,SI
- MOV MausY,DX
-
- MOV MouseUpdate,TRUE
- MOV DX,AX
- AND AX,LeftButtonPressed
- JE @noLeftButton
- MOV LeftButton,TRUE
- @noLeftButton:
- AND DX,RightButtonPressed
- JE @noRightButton
- MOV RightButton,TRUE
- @noRightButton:
-
- XOR AX,AX {Shift-Status der Tastatur auslesen:}
- MOV ES,AX {steht in mem[$40:$17] in den untersten 2 Bits}
- MOV SI,417h
- MOV AL,ES:[SI]
- AND AL,3
- JE @noShift
- MOV Shift,TRUE
- JMP @L1
- @noShift:
- MOV Shift,FALSE
-
- @L1:
- MOV AX,11
- INT 33h {Koordinatenänderung einlesen}
- MOV AX,mouseX2 {und Mauskoordinaten aktualisieren}
- ADD AX,CX
- CMP AX,MausMinX*2 {mouseX2:=max(MausMinX*2,mouseX2)}
- JGE @noSmall1
- MOV AX,MausMinX*2
- @noSmall1:
- CMP AX,MausMaxX_mul2 {mouseX2:=min(MausMaxX*2,mouseX2)}
- JLE @noBig1
- MOV AX,MausMaxX_mul2
- @noBig1:
- MOV mouseX2,AX
- SHR AX,1 {dem doofen Treiber doch noch eine Auflösung}
- MOV MausX,AX {von 640x400 Punkten abringen}
-
- MOV AX,mouseY2
- ADD AX,DX
- CMP AX,MausMinY*2 {mouseY2:=max(MausMinY*2,mouseY2)}
- JGE @noSmall2
- MOV AX,MausMinY*2
- @noSmall2:
- CMP AX,MausMaxY_mul2 {mouseY2:=min(MausMaxY*2,mouseY2)}
- JLE @noBig2
- MOV AX,MausMaxY_mul2
- @noBig2:
- MOV mouseY2,AX
- SHR AX,1
- MOV MausY,AX
-
- MOV SuppressMouse,TRUE
-
- @quit:
- pop es
- pop ds
- pop bp
- pop di
- pop si
- pop dx
- pop cx
- pop bx
- pop ax
- popf
- END;
- {$IFDEF StackCheck} {$S+} {$ENDIF}
-
- PROCEDURE PushAll;
- INLINE(
- $9C/ { PUSHF }
- $50/ { PUSH AX }
- $53/ { PUSH BX }
- $51/ { PUSH CX }
- $52/ { PUSH DX }
- $56/ { PUSH SI }
- $57/ { PUSH DI }
- $55/ { PUSH BP }
- $06/ { PUSH ES }
- $1E); { PUSH DS }
-
- PROCEDURE PopAll;
- INLINE(
- $1F/ { POP DS }
- $07/ { POP ES }
- $5D/ { POP BP }
- $5F/ { POP DI }
- $5E/ { POP SI }
- $5A/ { POP DX }
- $59/ { POP CX }
- $5B/ { POP BX }
- $58/ { POP AX }
- $9D); { POPF }
-
- FUNCTION LeftButtonStillPressed:BOOLEAN; ASSEMBLER;
- { in: - }
- {out: TRUE, falls linker Button noch immer gedrückt}
- ASM
- PUSHF
- PUSH BP
- PUSH DS
- MOV DI,OFFSET(@RestoreSS)
- MOV CS:[DI+1],SS
- MOV DI,OFFSET(@RestoreSP)
- MOV CS:[DI+1],SP
-
- mov ax,5
- mov bx,0
- int 33h
- and ax,1
-
- @RestoreSS:
- MOV SP,1234h
- MOV SS,SP
- @RestoreSP:
- MOV SP,1234h
-
- POP DS
- POP BP
- POPF
- END;
-
- PROCEDURE UpdateBox;
- { in: MausX,MausY = Koordinaten für Mauscursor}
- { MausXalt,MausYalt = Koord. des vorherigen Aufrufs}
- {rem: hierher, wenn Maus bewegt oder ein Button gedrückt wurde}
- BEGIN
- IF LeftButton OR LeftButtonStillPressed
- THEN BEGIN
- Sound(100); Delay(10); NoSound;
- WITH oldmouse DO
- BEGIN
- INC(breite,(MausXalt-MausX));
- INC(hoehe,(MausYalt-MausY));
- IF breite<1 THEN breite:=1;
- IF hoehe<1 THEN hoehe:=1
- END
- END;
- IF RightButton
- THEN BEGIN
- Sound(1000); Delay(10); NoSound;
- END;
- END;
-
- PROCEDURE initmouse;
- { in: MausMaxX,MausMaxY = max. zulässige Mausbildschirmkoordinaten}
- { MausCallBack = Maus-Event-Handler (FAR-Prozedur!) }
- {out: mouseX|Y2=MausMinX|Y*2, MausX|Y=MausMinX|Y}
- { Koordinatenbereich für Maus wurde entsprechend initialisert }
- { MausCallBack wird bei jeder Mausbewegung/Buttonbetätigung gerufen}
- { Maus ist "abgeschaltet" und muß erst mit "EnableMouse" aktiviert }
- { werden}
- {rem: Vorhandensein einer Maus muß vorher geprüft worden sein}
- { Koordinatenbereich wird verdoppelt, um Maustreiber eine echte }
- { Auflösung 0..MausMaxX,0..MausMaxY in Einerschritten abzuringen}
- BEGIN
- writeln(8);
-
- DisableMouse;
- mouseX2:=MausMinX*2; mouseY2:=MausMinY*2;
- MausX:=mouseX2 SHR 1; MausY:=mouseY2 SHR 1;
- MausXalt:=MausX; MausYalt:=MausY;
- MouseUpdate:=FALSE; LeftButton:=FALSE; RightButton:=FALSE;
-
- writeln(7);
-
- (* regs.ax := 0; Intr($33,regs); {Maustreiber initialisieren} *)
- PushAll;
- ASM
- MOV DI,OFFSET(@RestoreSS)
- MOV CS:[DI+1],SS
- MOV DI,OFFSET(@RestoreSP)
- MOV CS:[DI+1],SP
-
- mov ax,0
- int 33h
-
- @RestoreSS:
- MOV SP,1234h
- MOV SS,SP
- @RestoreSP:
- MOV SP,1234h
- END;
- PopAll;
-
- writeln(6);
-
- (* regs.ax := 2; Intr($33,regs); {Cursor aus} *)
- PushAll;
- ASM
- MOV DI,OFFSET(@RestoreSS)
- MOV CS:[DI+1],SS
- MOV DI,OFFSET(@RestoreSP)
- MOV CS:[DI+1],SP
-
- mov ax,2
- int 33h
-
- @RestoreSS:
- MOV SP,1234h
- MOV SS,SP
- @RestoreSP:
- MOV SP,1234h
- END;
- PopAll;
-
- writeln(5);
-
- (* regs.ax := 4; regs.cx := 0; regs.dx := 0; *)
- (* Intr($33,regs); {Maus in die obere linke Ecke setzen...} *)
- PushAll;
- ASM
- MOV DI,OFFSET(@RestoreSS)
- MOV CS:[DI+1],SS
- MOV DI,OFFSET(@RestoreSP)
- MOV CS:[DI+1],SP
-
- mov ax,4
- mov cx,0
- mov dx,0
- int 33h
-
- @RestoreSS:
- MOV SP,1234h
- MOV SS,SP
- @RestoreSP:
- MOV SP,1234h
- END;
- PopAll;
-
- Writeln(4);
-
- (* regs.ax := 7; regs.cx := 0; regs.dx := MausMaxX*2; *)
- (* Intr($33,regs); {x-Koordinatenbereich definieren} *)
- PushAll;
- ASM
- MOV DI,OFFSET(@RestoreSS)
- MOV CS:[DI+1],SS
- MOV DI,OFFSET(@RestoreSP)
- MOV CS:[DI+1],SP
-
- mov ax,7
- mov cx,0
- mov dx,MausMaxX_mul2
- int 33h
-
- @RestoreSS:
- MOV SP,1234h
- MOV SS,SP
- @RestoreSP:
- MOV SP,1234h
- END;
- PopAll;
-
- Writeln(3);
-
- (* regs.ax := 8; regs.cx := 0; regs.dx := MausMaxY*2; *)
- (* Intr($33,regs); {y-Koordinatenbereich definieren} *)
- PushAll;
- ASM
- MOV DI,OFFSET(@RestoreSS)
- MOV CS:[DI+1],SS
- MOV DI,OFFSET(@RestoreSP)
- MOV CS:[DI+1],SP
-
- mov ax,8
- mov cx,0
- mov dx,MausMaxY_mul2
- int 33h
-
- @RestoreSS:
- MOV SP,1234h
- MOV SS,SP
- @RestoreSP:
- MOV SP,1234h
- END;
- PopAll;
-
- writeln(2);
-
- (* regs.ax := 12; *)
- (* regs.cx := MouseMoved OR LeftButtonPressed OR RightButtonPressed; *)
- (* regs.es := seg(MouseCallBack); regs.dx := ofs(MouseCallBack); *)
- (* intr($33,regs); {Eigenen ISR installieren} *)
- PushAll;
- ASM
- MOV DI,OFFSET(@RestoreSS)
- MOV CS:[DI+1],SS
- MOV DI,OFFSET(@RestoreSP)
- MOV CS:[DI+1],SP
-
- mov ax,12
- mov cx,MouseMoved OR LeftButtonPressed OR RightButtonPressed
- mov dx,SEG MouseCallBack
- mov es,dx
- mov dx,OFFSET MouseCallBack
- int 33h
-
- @RestoreSS:
- MOV SP,1234h
- MOV SS,SP
- @RestoreSP:
- MOV SP,1234h
- END;
- PopAll;
-
- writeln(1);
- END;
-
-
- {------- noch ein paar Popup-Boxen definieren: --------}
- CONST ButtonWidth=(SizeOf(ButtonStringTyp)-1)*8; {Länge einer Textbox}
- EventOk=100;
- abfrage:ARRAY[1..2] OF box=(
- {"Ok"-Box:}
- (x1:0; y1:0; x2:0; y2:0;
- Name1:'';Name2:'';
- Show :Dummy;
- Event:EventOk;
- Click:TRUE; {Anclicken nötig}
- Paint:FALSE), {zeichnen tun wir selber!}
-
- {Sentinelwert, da x1>x2!}
- (x1:1; y1:0; x2:0; y2:0;
- Name1:'';Name2:'';
- Show :Dummy;
- Event:EventNone;
- Click:TRUE;
- Paint:TRUE)
- );
-
- {-------------------}
-
- EventYes=101;
- EventNo=102;
- alternative:ARRAY[1..3] OF box=(
- {"Ja"/"Nein"-Box:}
- {"Ja"-Box:}
- (x1:0; y1:0; x2:0; y2:0;
- Name1:'';Name2:'';
- Show :Dummy;
- Event:EventYes;
- Click:TRUE; {Anclicken nötig}
- Paint:FALSE), {zeichnen tun wir selber!}
-
- {"Nein"-Box:}
- (x1:0; y1:0; x2:0; y2:0;
- Name1:'';Name2:'';
- Show :Dummy;
- Event:EventNo;
- Click:TRUE;
- Paint:FALSE),
-
- {Sentinelwert, da x1>x2!}
- (x1:1; y1:0; x2:0; y2:0;
- Name1:'';Name2:'';
- Show :Dummy;
- Event:EventNone;
- Click:TRUE;
- Paint:TRUE)
- );
-
- {-------------------}
-
- VAR oldGraph:pointer;
- oldGraphSize:WORD;
-
- {-----Hintergrundbildspeicher: -----------}
- CONST XMAX=319; {Abmessungen einer Hintergrunddatei}
- YMAX=199;
- LINESIZE=(XMAX+1) DIV 4; {Groesse einer Zeile=80 Bytes}
- PAGESIZE=(YMAX+1)*LINESIZE; {200 Zeilen zu je 320/4 Bytes}
- TYPE bitmap=ARRAY[0..PAGESIZE-1] OF BYTE;
- bitmapPtr=^bitmap;
- bild=ARRAY[0..3] OF bitmapPtr;
-
- {-----Fehlerbehandlung: ------------------}
- CONST {Fehlercodes: }
- ErrNone=0;
- Error:BYTE=ErrNone;
-
- {-----Palette: --------------------------}
- TYPE PaletteEntry=RECORD red,green,blue:BYTE END;
- BigPalette=ARRAY[0..255] OF PaletteEntry;
- PalettePtr=^BigPalette;
- CONST DefaultColors:BigPalette= {Defaultfarben-Palette; erste 16-Farben}
- ( {sind identisch zu 16-Farbmodi-Farben! }
- (red: 0; green: 0; blue: 0), {Black}
- (red: 0; green: 0; blue: 42), {Blue }
- (red: 0; green: 42; blue: 0), {Green}
- (red: 0; green: 42; blue: 42), {Cyan }
- (red: 42; green: 0; blue: 0), {Red }
- (red: 42; green: 0; blue: 42), {Magenta }
- (red: 42; green: 21; blue: 0), {Brown}
- (red: 42; green: 42; blue: 42), {LightGray }
- (red: 21; green: 21; blue: 21), {DarkGray }
- (red: 21; green: 21; blue: 63), {LightBlue }
- (red: 21; green: 63; blue: 21), {LightGreen}
- (red: 21; green: 63; blue: 63), {LightCyan }
- (red: 63; green: 21; blue: 21), {LightRed }
- (red: 63; green: 21; blue: 63), {LightMagenta}
- (red: 63; green: 63; blue: 21), {Yellow}
- (red: 63; green: 63; blue: 63), {White }
- (red: 0; green: 0; blue: 0),
- (red: 5; green: 5; blue: 5),
- (red: 8; green: 8; blue: 8),
- (red: 11; green: 11; blue: 11),
- (red: 14; green: 14; blue: 14),
- (red: 17; green: 17; blue: 17),
- (red: 20; green: 20; blue: 20),
- (red: 24; green: 24; blue: 24),
- (red: 28; green: 28; blue: 28),
- (red: 32; green: 32; blue: 32),
- (red: 36; green: 36; blue: 36),
- (red: 40; green: 40; blue: 40),
- (red: 45; green: 45; blue: 45),
- (red: 50; green: 50; blue: 50),
- (red: 56; green: 56; blue: 56),
- (red: 63; green: 63; blue: 63),
- (red: 0; green: 0; blue: 63),
- (red: 16; green: 0; blue: 63),
- (red: 31; green: 0; blue: 63),
- (red: 47; green: 0; blue: 63),
- (red: 63; green: 0; blue: 63),
- (red: 63; green: 0; blue: 47),
- (red: 63; green: 0; blue: 31),
- (red: 63; green: 0; blue: 16),
- (red: 63; green: 0; blue: 0),
- (red: 63; green: 16; blue: 0),
- (red: 63; green: 31; blue: 0),
- (red: 63; green: 47; blue: 0),
- (red: 63; green: 63; blue: 0),
- (red: 47; green: 63; blue: 0),
- (red: 31; green: 63; blue: 0),
- (red: 16; green: 63; blue: 0),
- (red: 0; green: 63; blue: 0),
- (red: 0; green: 63; blue: 16),
- (red: 0; green: 63; blue: 31),
- (red: 0; green: 63; blue: 47),
- (red: 0; green: 63; blue: 63),
- (red: 0; green: 47; blue: 63),
- (red: 0; green: 31; blue: 63),
- (red: 0; green: 16; blue: 63),
- (red: 31; green: 31; blue: 63),
- (red: 39; green: 31; blue: 63),
- (red: 47; green: 31; blue: 63),
- (red: 55; green: 31; blue: 63),
- (red: 63; green: 31; blue: 63),
- (red: 63; green: 31; blue: 55),
- (red: 63; green: 31; blue: 47),
- (red: 63; green: 31; blue: 39),
- (red: 63; green: 31; blue: 31),
- (red: 63; green: 39; blue: 31),
- (red: 63; green: 47; blue: 31),
- (red: 63; green: 55; blue: 31),
- (red: 63; green: 63; blue: 31),
- (red: 55; green: 63; blue: 31),
- (red: 47; green: 63; blue: 31),
- (red: 39; green: 63; blue: 31),
- (red: 31; green: 63; blue: 31),
- (red: 31; green: 63; blue: 39),
- (red: 31; green: 63; blue: 47),
- (red: 31; green: 63; blue: 55),
- (red: 31; green: 63; blue: 63),
- (red: 31; green: 55; blue: 63),
- (red: 31; green: 47; blue: 63),
- (red: 31; green: 39; blue: 63),
- (red: 45; green: 45; blue: 63),
- (red: 49; green: 45; blue: 63),
- (red: 54; green: 45; blue: 63),
- (red: 58; green: 45; blue: 63),
- (red: 63; green: 45; blue: 63),
- (red: 63; green: 45; blue: 58),
- (red: 63; green: 45; blue: 54),
- (red: 63; green: 45; blue: 49),
- (red: 63; green: 45; blue: 45),
- (red: 63; green: 49; blue: 45),
- (red: 63; green: 54; blue: 45),
- (red: 63; green: 58; blue: 45),
- (red: 63; green: 63; blue: 45),
- (red: 58; green: 63; blue: 45),
- (red: 54; green: 63; blue: 45),
- (red: 49; green: 63; blue: 45),
- (red: 45; green: 63; blue: 45),
- (red: 45; green: 63; blue: 49),
- (red: 45; green: 63; blue: 54),
- (red: 45; green: 63; blue: 58),
- (red: 45; green: 63; blue: 63),
- (red: 45; green: 58; blue: 63),
- (red: 45; green: 54; blue: 63),
- (red: 45; green: 49; blue: 63),
- (red: 0; green: 0; blue: 28),
- (red: 7; green: 0; blue: 28),
- (red: 14; green: 0; blue: 28),
- (red: 21; green: 0; blue: 28),
- (red: 28; green: 0; blue: 28),
- (red: 28; green: 0; blue: 21),
- (red: 28; green: 0; blue: 14),
- (red: 28; green: 0; blue: 7),
- (red: 28; green: 0; blue: 0),
- (red: 28; green: 7; blue: 0),
- (red: 28; green: 14; blue: 0),
- (red: 28; green: 21; blue: 0),
- (red: 28; green: 28; blue: 0),
- (red: 21; green: 28; blue: 0),
- (red: 14; green: 28; blue: 0),
- (red: 7; green: 28; blue: 0),
- (red: 0; green: 28; blue: 0),
- (red: 0; green: 28; blue: 7),
- (red: 0; green: 28; blue: 14),
- (red: 0; green: 28; blue: 21),
- (red: 0; green: 28; blue: 28),
- (red: 0; green: 21; blue: 28),
- (red: 0; green: 14; blue: 28),
- (red: 0; green: 7; blue: 28),
- (red: 14; green: 14; blue: 28),
- (red: 17; green: 14; blue: 28),
- (red: 21; green: 14; blue: 28),
- (red: 24; green: 14; blue: 28),
- (red: 28; green: 14; blue: 28),
- (red: 28; green: 14; blue: 24),
- (red: 28; green: 14; blue: 21),
- (red: 28; green: 14; blue: 17),
- (red: 28; green: 14; blue: 14),
- (red: 28; green: 17; blue: 14),
- (red: 28; green: 21; blue: 14),
- (red: 28; green: 24; blue: 14),
- (red: 28; green: 28; blue: 14),
- (red: 24; green: 28; blue: 14),
- (red: 21; green: 28; blue: 14),
- (red: 17; green: 28; blue: 14),
- (red: 14; green: 28; blue: 14),
- (red: 14; green: 28; blue: 17),
- (red: 14; green: 28; blue: 21),
- (red: 14; green: 28; blue: 24),
- (red: 14; green: 28; blue: 28),
- (red: 14; green: 24; blue: 28),
- (red: 14; green: 21; blue: 28),
- (red: 14; green: 17; blue: 28),
- (red: 20; green: 20; blue: 28),
- (red: 22; green: 20; blue: 28),
- (red: 24; green: 20; blue: 28),
- (red: 26; green: 20; blue: 28),
- (red: 28; green: 20; blue: 28),
- (red: 28; green: 20; blue: 26),
- (red: 28; green: 20; blue: 24),
- (red: 28; green: 20; blue: 22),
- (red: 28; green: 20; blue: 20),
- (red: 28; green: 22; blue: 20),
- (red: 28; green: 24; blue: 20),
- (red: 28; green: 26; blue: 20),
- (red: 28; green: 28; blue: 20),
- (red: 26; green: 28; blue: 20),
- (red: 24; green: 28; blue: 20),
- (red: 22; green: 28; blue: 20),
- (red: 20; green: 28; blue: 20),
- (red: 20; green: 28; blue: 22),
- (red: 20; green: 28; blue: 24),
- (red: 20; green: 28; blue: 26),
- (red: 20; green: 28; blue: 28),
- (red: 20; green: 26; blue: 28),
- (red: 20; green: 24; blue: 28),
- (red: 20; green: 22; blue: 28),
- (red: 0; green: 0; blue: 16),
- (red: 4; green: 0; blue: 16),
- (red: 8; green: 0; blue: 16),
- (red: 12; green: 0; blue: 16),
- (red: 16; green: 0; blue: 16),
- (red: 16; green: 0; blue: 12),
- (red: 16; green: 0; blue: 8),
- (red: 16; green: 0; blue: 4),
- (red: 16; green: 0; blue: 0),
- (red: 16; green: 4; blue: 0),
- (red: 16; green: 8; blue: 0),
- (red: 16; green: 12; blue: 0),
- (red: 16; green: 16; blue: 0),
- (red: 12; green: 16; blue: 0),
- (red: 8; green: 16; blue: 0),
- (red: 4; green: 16; blue: 0),
- (red: 0; green: 16; blue: 0),
- (red: 0; green: 16; blue: 4),
- (red: 0; green: 16; blue: 8),
- (red: 0; green: 16; blue: 12),
- (red: 0; green: 16; blue: 16),
- (red: 0; green: 12; blue: 16),
- (red: 0; green: 8; blue: 16),
- (red: 0; green: 4; blue: 16),
- (red: 8; green: 8; blue: 16),
- (red: 10; green: 8; blue: 16),
- (red: 12; green: 8; blue: 16),
- (red: 14; green: 8; blue: 16),
- (red: 16; green: 8; blue: 16),
- (red: 16; green: 8; blue: 14),
- (red: 16; green: 8; blue: 12),
- (red: 16; green: 8; blue: 10),
- (red: 16; green: 8; blue: 8),
- (red: 16; green: 10; blue: 8),
- (red: 16; green: 12; blue: 8),
- (red: 16; green: 14; blue: 8),
- (red: 16; green: 16; blue: 8),
- (red: 14; green: 16; blue: 8),
- (red: 12; green: 16; blue: 8),
- (red: 10; green: 16; blue: 8),
- (red: 8; green: 16; blue: 8),
- (red: 8; green: 16; blue: 10),
- (red: 8; green: 16; blue: 12),
- (red: 8; green: 16; blue: 14),
- (red: 8; green: 16; blue: 16),
- (red: 8; green: 14; blue: 16),
- (red: 8; green: 12; blue: 16),
- (red: 8; green: 10; blue: 16),
- (red: 11; green: 11; blue: 16),
- (red: 12; green: 11; blue: 16),
- (red: 13; green: 11; blue: 16),
- (red: 15; green: 11; blue: 16),
- (red: 16; green: 11; blue: 16),
- (red: 16; green: 11; blue: 15),
- (red: 16; green: 11; blue: 13),
- (red: 16; green: 11; blue: 12),
- (red: 16; green: 11; blue: 11),
- (red: 16; green: 12; blue: 11),
- (red: 16; green: 13; blue: 11),
- (red: 16; green: 15; blue: 11),
- (red: 16; green: 16; blue: 11),
- (red: 15; green: 16; blue: 11),
- (red: 13; green: 16; blue: 11),
- (red: 12; green: 16; blue: 11),
- (red: 11; green: 16; blue: 11),
- (red: 11; green: 16; blue: 12),
- (red: 11; green: 16; blue: 13),
- (red: 11; green: 16; blue: 15),
- (red: 11; green: 16; blue: 16),
- (red: 11; green: 15; blue: 16),
- (red: 11; green: 13; blue: 16),
- (red: 11; green: 12; blue: 16),
- (red: 0; green: 0; blue: 0),
- (red: 0; green: 0; blue: 0),
- (red: 0; green: 0; blue: 0),
- (red: 0; green: 0; blue: 0),
- (red: 0; green: 0; blue: 0),
- (red: 0; green: 0; blue: 0),
- (red: 0; green: 0; blue: 0),
- (red: 0; green: 0; blue: 0)
- );
- VAR ActualColors :BigPalette;{aktuelle Farben}
-
- FUNCTION PalEqual(p1,p2:BigPalette):BOOLEAN;
- { in: p1,p2 = zu vergleichende Paletten}
- {out: p1=p2 }
- VAR i:WORD;
- flag:BOOLEAN;
- BEGIN
- i:=0;
- REPEAT
- flag:= (p1[i].red =p2[i].red)
- AND (p1[i].green=p2[i].green)
- AND (p1[i].blue =p2[i].blue);
- inc(i);
- UNTIL (i>255) OR (NOT flag);
- PalEqual:=flag
- END;
-
- PROCEDURE GetBigPalette(VAR pal:BigPalette); ASSEMBLER;
- { in: pal = Zeiger auf Palette-Speicher}
- {out: pal = momentan aktueller Inhalt der 256-Farben CLUT}
- ASM
- CLI
- XOR AL,AL
- MOV DX,3C7h
- OUT DX,AL
- LES DI,pal
- MOV CX,768
- MOV DX,3C9h
- @L1:
- IN AL,DX
- STOSB
- LOOP @L1
- STI
- END;
-
- FUNCTION BestFit(Color:BYTE):BYTE; ASSEMBLER;
- { in: Color = Farbnummer des 16 Farbmodus, die approximiert werden soll}
- { ActualColors = gerade gesetzte 256 Farben}
- { DefaultColors= Tabelle der Defaultfarben der 16 (256) Farbmodi}
- {out: Farbnummer, deren Farbe am ehesten der uebergebenen Farbe entspricht}
- {rem: von Defaultcolors werden nur die ersten 16 Eintraege benoetigt, um }
- { die Umsetzung Farbname -> RGB-Tripel machen zu koennen!}
- ASM
- MOV BL,Color
- XOR BH,BH
- MOV SI,BX
- SHL SI,1
- ADD SI,BX
- ADD SI,OFFSET DefaultColors
- MOV BX,[SI]
- MOV DH,[SI+2] {BL/BH/DH = aktuelle Farbe, RGB}
-
- PUSH BP
- MOV DI,65535 {DI=bisher gefundenes minimales Fehlerquadrat}
- MOV CX,255
- MOV SI,OFFSET ActualColors {DS:SI = Zeiger auf aktuelle Farben}
-
- @searchloop:
- MOV AL,BL
- SUB AL,[SI] {Farbdifferenz im Rotanteil}
- IMUL AL {Fehler*quadrat* optimieren}
- MOV BP,AX
-
- MOV AL,BH {dto., Gruenanteil}
- SUB AL,[SI+1]
- IMUL AL
- ADD BP,AX
- JC @noNewMin
-
- MOV AL,DH {dto., Blauanteil}
- SUB AL,[SI+2]
- IMUL AL
- ADD AX,BP
- JC @noNewMin
-
- CMP AX,DI
- JAE @noNewMin
- MOV DI,AX
- MOV DL,CL {100h-DL=bisher optimale Farbe}
- @noNewMin:
- ADD SI,3 {naechste Farbe zum Vergleich}
- LOOP @searchloop
-
- POP BP
-
- MOV AL,DL
- NOT AL {AL:=100h-DL = optimale Farbe}
- XOR AH,AH
- END;
-
- PROCEDURE SetPalette(pal:BigPalette);
- { in: pal = Zeiger auf zu setzende Palette }
- { StatusReg = Statusregister der VGA-Karte}
- {out: Best* = Farbnummern der gerade gesetzten}
- { Palette, die den Fraben am ähnlichsten sind }
- {rem: Palette wurde uebernommen}
- VAR p:PalettePtr;
- BEGIN
- p:=@pal; {Trick, da der Assembler nicht mit dem SS-Segment klarkommt}
- ASM
- mov dx,StatusReg
-
- PUSH DS
- LDS SI,p
-
- CLI
- @WaitNotVSyncLoop:
- in al,dx
- and al,8
- jnz @WaitNotVSyncLoop
- @WaitVSyncLoop:
- in al,dx
- and al,8
- jz @WaitVSyncLoop
-
- MOV DX,3C8h
- XOR AL,AL
- OUT DX,AL
- INC DX
-
- MOV CX,256
- @L1:
- LODSB
- OUT DX,AL
- LODSB
- OUT DX,AL
- LODSB
- OUT DX,AL
- LOOP @L1
-
- STI
- POP DS
- END; {of ASM}
- BestWhite:=BestFit(White);
- BestBlack:=BestFit(Black);
- BestCyan :=BestFit(Cyan);
- BestLightGray:=BestFit(LightGray);
- BestDarkGray:=BestFit(DarkGray);
- END;
-
- PROCEDURE SetPaletteEntry(nr,rot,gruen,blau:BYTE); ASSEMBLER;
- { in: nr = zu setzende Farbe}
- { rot,gruen,blau = deren RGB-Werte (0..63)}
- { StatusReg = Portadresse des VGA-Statusregisters}
- {out: - }
- {rem: Die entsprechende Farbe wurde verändert}
- ASM
- MOV AH,rot
- MOV BL,gruen
- MOV BH,blau
- MOV SI,3C8h
- MOV CL,nr
- MOV DX,StatusReg
-
- CLI
- @WaitNotHSync:
- IN AL,DX
- TEST AL,1
- JNE @WaitNotHSync
- @WaitHSync:
- IN AL,DX
- TEST AL,1
- JE @WaitHSync
-
- MOV DX,SI
- MOV AL,CL
- OUT DX,AL {Farbnr. an 3C8h}
- INC DX
- MOV AL,AH
- OUT DX,AL {rot an 3C9h}
- MOV AL,BL
- OUT DX,AL {gruen auch}
- MOV AL,BH
- OUT DX,AL {blau auch}
- STI
- END;
-
-
- {---------------------------------------------}
- var n,x,y,button:integer;
- s:String[5];
- ch,ch2:Char;
- buttonzahl,i,j:Integer;
- FarbenStartX,FarbenStartY,FarbenHoehegesamt,
- Koordmeldx,Koordmeldy, {Koordinaten für X/Y-Angabe}
- FilenameStartX,FilenameStartY:Integer; {dto., für Filename}
- PalnameStartX ,PalnameStartY :Integer; {dto., für Filename}
- Filenamelang,Filenamekurz: PathStr; {Dateinamen mit/ohne Pfadangabe}
- Palnamelang ,Palnamekurz : PathStr; {Palettennnamen m/o Pfadangabe }
- oldNamelang ,oldNamekurz : PathStr;
- Wahl:WORD;
-
- PROCEDURE ErrBeep;
- BEGIN
- sound(100); delay(300); nosound;
- END;
-
- function DetectVGA256 : Integer; FAR;
- VAR ch:CHAR;
- begin
- ClrScr;
- WRITELN('Select one of the following graphic modes:');
- WRITELN('320x200x256 = 0 ');
- WRITELN('640x400x256 = 1 ');
- WRITELN('640x480x256 = 2 ');
- WRITELN('800x600x256 = 3 ');
- WRITELN('1024x768x256 = 4 ');
- WRITELN;
- WRITELN('ATTENTION! Depending on your VGA''s chipset, some of the modes may not be');
- WRITELN('supported by your system.');
- REPEAT
- WRITE('Your choice: ');
- ch:=ReadKey;
- CASE ch OF
- '0': DetectVGA256 := SVGA320x200x256;
- '1': DetectVGA256 := SVGA640x400x256;
- '2': DetectVGA256 := SVGA640x480x256;
- '3': DetectVGA256 := SVGA800x600x256;
- '4': DetectVGA256 := SVGA1024x768x256;
- ELSE BEGIN
- WRITELN(ch);
- WRITELN('Gee man, I said: a number between 0..4!');
- Sound(200); Delay(200); Nosound;
- END;
- END;
- UNTIL ch IN ['0'..'4'];
- end;
-
- VAR GraphMode,GraphDriver:INTEGER;
-
- PROCEDURE InitGrafikDisplay;
- VAR Fehler : integer;
- Size : LongInt;
- BEGIN
- GraphDriver := detect;
- InitGraph(GraphDriver,GraphMode,'');
- Fehler:=GraphResult;
-
- IF Fehler<>GrOK
- THEN BEGIN
- restorecrtmode;
- WRITELN('*** Error while initializing graphic:');
- CASE Fehler OF
- -2:WRITELN('No graphic card found.');
- -3:WRITELN('Could not find *.BGI-driver.');
- -4:WRITELN('Graphic driver has wrong format.');
- -5:WRITELN('Not enough memory to load graphic driver.');
- else WRITELN('Errorcode: ',Fehler);
- END;
- Halt(1);
- END;
-
- Fehler:=GraphResult;
-
- IF Fehler<>0
- THEN BEGIN
- restorecrtmode;
- WRITELN('*** Unknown graphic error (while trying to switch into'+
- ' the 256-color-mode).');
- WRITELN('Errorcode: ',Fehler);
- END
- ELSE BEGIN
- ActualColors:=DefaultColors;
- SetPalette(ActualColors); {aktuelle Farben=Defaultfarben}
- END;
-
- END;
-
- PROCEDURE ShowCursorDaten;
- { in: MausX,MausY = aktuelle Mauskoordinaten, innerhalb der Workarea!}
- { zoom = aktueller Zoomfaktor}
- {out: Ausgabe der relativen Mauskoordinaten bzgl. der Workarea am Schirm}
- { und der Farbe unter dem Mauscursor}
- {rem: Dieselben Koordinaten werden im Hauptprogramm nochmals benötigt, }
- { bei einer Änderung dort also auch ändern!}
- VAR relX,relY:INTEGER;
- b:BYTE;
- s:STRING[3];
- BEGIN
- END;
-
- FUNCTION sign(a:INTEGER):INTEGER;
- BEGIN
- IF a<0 THEN sign:=-1
- ELSE IF a>0 THEN sign:=+1
- ELSE sign:=0
- END;
-
-
- PROCEDURE FindVGARegisters; ASSEMBLER;
- { in: - }
- {out: CRTAddress = Adresse des CRT-Ports, $3B4/$3D4 für monochrom/Farbe}
- { StatusReg = dto., für Statusregister, $3BA/$3DA}
- ASM
- MOV DX,3CCh
- IN AL,DX
- TEST AL,1
- MOV DX,3D4h
- JNZ @L1
- MOV DX,3B4h
- @L1:
- MOV CRTAddress,DX
- ADD DX,6
- MOV StatusReg,DX
- END;
-
- PROCEDURE init;
- { prüft + initialisiert Maus, reserviert Platz für Mausmaske}
- { initialisiert Grafik, sucht VGA-Karten-spezifische Grafikregister}
- { reserviert Platz für Workarea-Inhalt}
- { initialisiert Grafikbildschirm}
- { initialisiert Variablen: Filename*, Palname*, Farben*, Koordmeld?}
- { Event=EventNone}
- BEGIN
- writeln(11);
- IF NOT MouseInstalled
- THEN BEGIN {Ohne Maus läuft nix!}
- WRITELN(#7+'Error! Couldn''t detect mouse!');
- Halt(1)
- END
- ELSE BEGIN
- SwapVectors;
- initmouse;
- END;
-
- FindVGARegisters;
- InitGrafikDisplay;
-
- Event:=EventNone;
-
- MausMaxX:=GetMaxX;
- MausMaxY:=GetMaxY;
- MausMaxX_mul2:=GetMaxX*2;
- MausMaxY_mul2:=GetMaxY*2;
- Menu[1].x2:=MausMaxX; Menu[1].y2:=MausMaxY;
- oldMouse.breite:=MausMaxX-MausX+1;
- oldMouse.hoehe :=MausMaxY-MausY+1;
- MeldungX:=GetMaxX DIV 4;
- MeldungY:=GetMaxY DIV 4;
- IF (GetMaxX-MeldungX)<150 THEN MeldungX:=0;
- IF (GetMaxY-MeldungY)<100 THEN MeldungY:=0;
-
- FileNameLang:='';
- FileNameKurz:='';
- PalNameLang:='';
- PalNameKurz:='';
- END;
-
- PROCEDURE DrawOkBox(x1,y1,x2,y2:WORD; Text1:ButtonStringTyp;
- s1,s2,s3:STRING; VAR menu);
- { in: s1|s2|s3 = auszugebende Strings}
- { Text1 = beschriftung für anzuzeigenden Button}
- { x1,y1 = linke obere Ecke der Meldungsbox (absolute Koord.) }
- { x2,y2 = rechte untere Ecke der Meldungsbox (absolute Koord.)}
- { menu = auszugebende Menubox}
- {out: oldGraph^ = alter Inhalt unter Meldebox}
- { oldGraphSize = deren Größe}
- { menu = um Koordinaten erweiterte Menubox (=für }
- { AskOkBox() vorbereitet}
- {rem: Grafikmodus muß bereits aktiv sein!}
- { Length(s1|s2|s3)*8 >= x2-x1+1 !}
- { Der Meldungsboxbereich muß kleiner als 64K sein!}
- { Das Menu darf höchstens aus 10 Boxen bestehen}
- VAR BoxBreite,BoxHoehe,disx,disy:INTEGER;
- x,y:WORD;
- mymenu:ARRAY[1..10] OF box ABSOLUTE menu;
- BEGIN
- {alte Grafik sichern:}
- oldGraphSize:=ImageSize(x1,y1,x2,y2);
- GetMem(oldGraph,oldGraphSize);
- GetImage(x1,y1,x2,y2,oldGraph^);
-
- SetFillStyle(SolidFill,BestLightGray);
- Bar(x1,y1,x2,y2);
- SetFillStyle(SolidFill,BestWhite);
- Bar(x1,y1,x2-1,y1+1);
- Bar(x1,y1,x1+1,y2-1);
- SetFillStyle(SolidFill,BestDarkGray);
- Bar(x1,y2-1,x2,y2);
- Bar(x2-1,y1,x2,y2);
-
- BoxBreite:=Succ(x2-x1); BoxHoehe:=Succ(y2-y1);
- SetColor(BestBlack);
- y:=y1+10;
- IF s1<>''
- THEN BEGIN
- OutTextXY(x1+ (BoxBreite -(Length(s1) SHL 3)) SHR 1,y,s1);
- INC(y,10);
- END;
- IF s2<>''
- THEN BEGIN
- OutTextXY(x1+ (BoxBreite -(Length(s2) SHL 3)) SHR 1,y,s2);
- INC(y,10);
- END;
- IF s3<>''
- THEN BEGIN
- OutTextXY(x1+ (BoxBreite -(Length(s3) SHL 3)) SHR 1,y,s3);
- INC(y,10);
- END;
-
- disx:=(BoxBreite-ButtonWidth) DIV 2;
- disy:=(BoxHoehe-(y-y1)) DIV 4;
- mymenu[1].x1:=x1+disx; mymenu[1].y1:=y+disy;
- mymenu[1].x2:=x2-disx; mymenu[1].y2:=y2-disy;
-
- {Jetzt die Box einzeichnen:}
- y:=y+disy + ((y2-disy)-(y+disy)-8) SHR 1; {für's zentrieren des Textes...}
- WITH mymenu[1] DO
- BEGIN
- SetFillStyle(SolidFill,BestLightGray);
- Bar(x1,y1,x2,y2);
- SetFillStyle(SolidFill,BestWhite);
- Bar(x1,y1,x2-1,y1+1);
- Bar(x1,y1,x1+1,y2-1);
- SetFillStyle(SolidFill,BestDarkGray);
- Bar(x1,y2-1,x2,y2);
- Bar(x2-1,y1,x2,y2);
- OutTextXY(x1+ (ButtonWidth-(Length(Text1) SHL 3)) SHR 1,y,Text1);
- END;
- END;
-
- PROCEDURE AskOkBox(x1,y1:WORD; VAR menu);
- { in: menu = komplett ausgefüllte Menubox}
- { oldGraph^ = alte Grafikdaten}
- { oldGraphSize = deren Größe }
- {out: Event = aufgetretenes Event }
- {rem: Maus wird freigegeben, um lokales Menu bearbeiten zu können!}
- { Das Menu darf höchstens aus 10 Boxen bestehen}
- VAR mymenu:ARRAY[1..10] OF box ABSOLUTE menu;
- ch:CHAR;
- BEGIN;
- ch:=#0;
- DrawMaus;
- Event:=EventNone;
-
- {Maus freigeben:}
- ClearMouse;
-
- REPEAT
- IF MouseUpdate
- THEN BEGIN
- UndrawMaus;
- Event:=MouseEvent(mymenu);
- IF (Event=EventNone)
- THEN BEGIN {das war nichts, nochmal!}
- DrawMaus;
- ClearMouse;
- END;
- END;
- WHILE KeyPressed DO ch:=ReadKey;
- IF ch<>#0
- THEN Event:=EventOK; {auch per Taste abbrechbar}
- UNTIL Event<>EventNone;
-
- UndrawMaus;
- {alte Grafik wiederherstellen:}
- PutImage(x1,y1,oldGraph^,NormalPut);
- FreeMem(oldGraph,oldGraphSize);
- END;
-
- PROCEDURE OkBox(x1,y1,x2,y2:WORD; Text1:ButtonStringTyp;
- s1,s2,s3:STRING; VAR menu);
- { in: s1|s2|s3 = auszugebende Strings}
- { x1,y1 = linke obere Ecke der Meldungsbox (absolute Koord.) }
- { x2,y2 = rechte untere Ecke der Meldungsbox (absolute Koord.)}
- { Text1 = Beschriftung für auszugebenden Button}
- { menu = auszugebende Ok-Box}
- {out: (In menu wurden die Koordinaten verändert, was aber ohne Bedeutung}
- { sein sollte, da die übergebenen Menus eh nur für diesen Zweck ge- }
- { dacht sind)}
- { Event = aufgetretenes Event}
- {rem: Grafikmodus muß bereits aktiv sein!}
- { Length(s1|s2|s3)*8 >= x2-x1+1 !}
- { Maus wird freigegeben, um lokales Menu bearbeiten zu können!}
- { Der Meldungsboxbereich muß kleiner als 64K sein!}
- { Das Menu darf höchstens aus 10 Boxen bestehen}
- BEGIN
- DrawOkBox(x1,y1,x2,y2,Text1,s1,s2,s3,menu);
- AskOkBox(x1,y1,menu);
- END;
-
- PROCEDURE DrawFirstOfTwoBoxes(x1,y1,x2,y2:WORD;
- Text1,Text2:ButtonStringTyp;
- s1,s2,s3:STRING;
- VAR menu);
- { in: s1|s2|s3 = auszugebende Strings}
- { Text1|2 = Beschriftung der beiden Buttons}
- { x1,y1 = linke obere Ecke der Meldungsbox (absolute Koord.) }
- { x2,y2 = rechte untere Ecke der Meldungsbox (absolute Koord.)}
- { menu = auszugebndes Menu}
- {out: TRUE|FALSE für erste|zweite Box angeclickt}
- { menu = um Koordinaten erweitertes Menu}
- {rem: Grafikmodus muß bereits aktiv sein!}
- { Length(s1|s2|s3)*8 >= x2-x1+1 !}
- { Maus wird freigegeben, um lokales Menu bearbeiten zu können!}
- { Der Meldungsboxbereich muß kleiner als 64K sein!}
- { Das Menu darf höchstens aus 10 Boxen bestehen}
- VAR BoxBreite,BoxHoehe,disx,disy:INTEGER;
- x,y:WORD;
- mymenu:ARRAY[1..10] OF box ABSOLUTE menu;
- BEGIN
- {alte Grafik sichern:}
- oldGraphSize:=ImageSize(x1,y1,x2,y2);
- GetMem(oldGraph,oldGraphSize);
- GetImage(x1,y1,x2,y2,oldGraph^);
-
- SetFillStyle(SolidFill,BestLightGray);
- Bar(x1,y1,x2,y2);
- SetFillStyle(SolidFill,BestWhite);
- Bar(x1,y1,x2-1,y1+1);
- Bar(x1,y1,x1+1,y2-1);
- SetFillStyle(SolidFill,BestDarkGray);
- Bar(x1,y2-1,x2,y2);
- Bar(x2-1,y1,x2,y2);
-
- BoxBreite:=Succ(x2-x1); BoxHoehe:=Succ(y2-y1);
- SetColor(BestBlack);
- y:=y1+10;
- IF s1<>''
- THEN BEGIN
- OutTextXY(x1+ (BoxBreite -(Length(s1) SHL 3)) SHR 1,y,s1);
- INC(y,10);
- END;
- IF s2<>''
- THEN BEGIN
- OutTextXY(x1+ (BoxBreite -(Length(s2) SHL 3)) SHR 1,y,s2);
- INC(y,10);
- END;
- IF s3<>''
- THEN BEGIN
- OutTextXY(x1+ (BoxBreite -(Length(s3) SHL 3)) SHR 1,y,s3);
- INC(y,10);
- END;
-
- disx:=(BoxBreite-(ButtonWidth SHL 1)) DIV 3;
- disy:=(BoxHoehe-(y-y1)) DIV 4;
- mymenu[1].x1:=x1+disx; mymenu[1].y1:=y+disy;
- mymenu[1].x2:=x1+disx+ButtonWidth; mymenu[1].y2:=y2-disy;
-
- mymenu[2].x1:=x2-disx-ButtonWidth; mymenu[2].y1:=y+disy;
- mymenu[2].x2:=x2-disx; mymenu[2].y2:=y2-disy;
-
- {Jetzt die beiden Boxen einzeichnen:}
- y:=y+disy + ((y2-disy)-(y+disy)-8) SHR 1; {für's zentrieren des Textes...}
- WITH mymenu[1] DO
- BEGIN
- SetFillStyle(SolidFill,BestLightGray);
- Bar(x1,y1,x2,y2);
- SetFillStyle(SolidFill,BestWhite);
- Bar(x1,y1,x2-1,y1+1);
- Bar(x1,y1,x1+1,y2-1);
- SetFillStyle(SolidFill,BestDarkGray);
- Bar(x1,y2-1,x2,y2);
- Bar(x2-1,y1,x2,y2);
- OutTextXY(x1+ (ButtonWidth-(Length(Text1) SHL 3)) SHR 1,y,Text1);
- END;
-
- WITH mymenu[2] DO
- BEGIN
- SetFillStyle(SolidFill,BestLightGray);
- Bar(x1,y1,x2,y2);
- SetFillStyle(SolidFill,BestWhite);
- Bar(x1,y1,x2-1,y1+1);
- Bar(x1,y1,x1+1,y2-1);
- SetFillStyle(SolidFill,BestDarkGray);
- Bar(x1,y2-1,x2,y2);
- Bar(x2-1,y1,x2,y2);
- OutTextXY(x1+ (ButtonWidth-(Length(Text2) SHL 3)) SHR 1,y,Text2);
- END;
-
- DrawMaus;
- {Maus freigeben:}
- ClearMouse;
- END;
-
- FUNCTION AskFirstOfTwoBoxes(x1,y1:WORD; Text1,Text2:ButtonStringTyp;
- VAR menu):BOOLEAN;
- { in: menu = komplett ausgefüllte Menubox}
- { oldGraph^ = alte Grafikdaten}
- { oldGraphSize = deren Größe }
- {out: Event = aufgetretenes Event }
- {rem: Maus wird freigegeben, um lokales Menu bearbeiten zu können!}
- { Das Menu darf höchstens aus 10 Boxen bestehen}
- VAR ch:CHAR;
- mymenu:ARRAY[1..10] OF box ABSOLUTE menu;
- BEGIN
- Event:=EventNone;
- REPEAT
- IF MouseUpdate
- THEN BEGIN
- UndrawMaus;
- Event:=MouseEvent(mymenu);
- IF (Event=EventNone)
- THEN BEGIN {das war nichts, nochmal!}
- DrawMaus;
- ClearMouse;
- END;
- END
- ELSE IF (KeyPressed) AND (Upcase(Text1[1])<>Upcase(Text2[1])) THEN
- BEGIN
- WHILE KeyPressed DO ch:=Upcase(ReadKey);
- IF ch=Upcase(Text1[1]) THEN Event:=mymenu[1].Event
- ELSE IF ch=Upcase(Text2[1]) THEN Event:=mymenu[2].Event;
- END;
- UNTIL Event<>EventNone;
-
- UndrawMaus;
- {alte Grafik wiederherstellen:}
- PutImage(x1,y1,oldGraph^,NormalPut);
- FreeMem(oldGraph,oldGraphSize);
-
- AskFirstOfTwoBoxes:=Event=EventYes
- END;
-
- FUNCTION FirstOfTwoBoxes(x1,y1,x2,y2:WORD;
- Text1,Text2:ButtonStringTyp;
- s1,s2,s3:STRING;
- VAR menu):BOOLEAN;
- { in: s1|s2|s3 = auszugebende Strings}
- { Text1|2 = Beschriftung der beiden Buttons}
- { x1,y1 = linke obere Ecke der Meldungsbox (absolute Koord.) }
- { x2,y2 = rechte untere Ecke der Meldungsbox (absolute Koord.)}
- { menu = auszugebendes Menu}
- {out: TRUE|FALSE für erste|zweite Box angeclickt}
- { (In "menu" wurden die Koordinaten verändert, was aber keine }
- { Probleme verursachen sollte, da die übergebenen Menus eh nur}
- { für diesen Zweck gedacht sind)}
- { Event = aufgetretenes Event}
- {rem: Grafikmodus muß bereits aktiv sein!}
- { Length(s1|s2|s3)*8 >= x2-x1+1 !}
- { Maus wird freigegeben, um lokales Menu bearbeiten zu können!}
- { Der Meldungsboxbereich muß kleiner als 64K sein!}
- { Das Menu darf höchstens aus 10 Boxen bestehen}
- BEGIN
- DrawFirstOfTwoBoxes(x1,y1,x2,y2,Text1,Text2,s1,s2,s3,menu);
- FirstOfTwoBoxes:=AskFirstOfTwoBoxes(x1,y1,Text1,Text2,menu);
- END;
-
- PROCEDURE Help;
- BEGIN
- OkBox((GetMaxX-300) SHR 1,MeldungY,(GetMaxX-300) SHR 1+300,MeldungY+60,'ok',
- 'To resize the box: press the left',
- 'button and drag. Press the right',
- 'button to save a file; ESC quits.',Abfrage);
- END;
-
-
-
-
-
-
-
- PROCEDURE DisplayPCXagain; FORWARD;
-
- CONST MaxSize=65520;
- transparent=0; {Farbe für durchsichtig = 0 per Definition!}
- {Farben für Text-Selektionsboxen:}
- ChoseColor=blue shl 4 + white; {weiße Schrift auf blauem Hintergrund}
-
- Kopf=50; {size of sprite header}
- TYPE spritetyp= record case Integer of
- 0:(
- Zeiger_auf_Plane:Array[0..3] OF Word; {These... }
- Breite_in_4er_Gruppen:WORD; {...data }
- Hoehe_in_Zeilen:WORD; {...use }
- Translate:Array[1..4] OF Byte; {...all }
- SpriteLength:WORD; {...in all}
- Dummy:Array[1..10] OF Word;
- Kennung:ARRAY[1..2] OF CHAR;
- Version:BYTE;
- Modus:BYTE;
- ZeigerL,ZeigerR,ZeigerO,ZeigerU:Word; {"Head" bytes!}
- Data:Array[0..MaxSize-Kopf] OF Byte;
- );
- 1:(
- readin:Array[0..MaxSize] OF Byte;
- )
- END;
-
- TYPE WorkAreaTyp=ARRAY[0..MaxSize] OF BYTE;
- PWorkAreaTyp=^WorkAreaTyp;
- VAR WorkArea:RECORD
- SizeX,SizeY:WORD; {Größe in x- und y-Richtung}
- MaxUsedX,MaxUsedY:INTEGER;
- data:PWorkAreaTyp; {Zeiger auf Datenarray}
- END;
-
- PROCEDURE SaveActualColors;
- { in: ActualColors = abzuspeichernde 256-Farbenpalette}
- { FileNameLang = Name der abzuspeichernden Datei; die Extension}
- { muß allerdings noch auf ".PAL" gebracht werden}
- {out: Palette wurde unter dem entsprechenden Namen abgespeichert}
- VAR f:FILE;
- D:DirStr;
- N:NameStr;
- E:ExtStr;
- BEGIN
- FSplit(FileNameLang,D,N,E);
- Assign(f,D+N+'.PAL');
- ReWrite(f,1);
- BlockWrite(f,ActualColors,SizeOf(ActualColors));
- Close(f)
- END;
-
- PROCEDURE SpeichereHintergrund; {PIC's}
- { in: Filenamelang = Name der zu schreibenden Datei}
- { oldName* = alte Dateinamen}
- { Workarea^.[] = zu schreibende Daten}
- {out: Falls Sprite nicht erstellt werden konnte, wurden die alten}
- { Dateinamen für Filename* wieder eingesetzt!}
- {rem: Der Inhalt der Workarea wird in die Datei Filenamelang }
- { geschrieben; der Dateiname wurde bereits auf Eröffenbar-}
- { keit geprüft, ebenso, daß die Workarea nicht leer ist! }
- CONST PICHeader:STRING[3]='PIC'; {Kennung in Bilderdateien}
- VAR f:File;
- s:String[20];
- i:BYTE;
- t,x,y:WORD;
- picture:Bild;
- pp:POINTER;
- pplen:WORD;
- attr:BYTE;
- BEGIN
- IF MaxAvail<4*SizeOf(BitMap)
- THEN BEGIN
- attr:=TextAttr; TextColor(White); TextBackground(Blue);
- GotoXY(10,5);
- WRITE('Not enough heap memory to complete action!');
- GotoXY(10,6);
- WRITE(' needed memory : ',4*SizeOf(BitMap):7,' bytes ');
- GotoXY(10,7);
- WRITE(' available memory: ',MaxAvail:7,' bytes ');
- Rahmen(9,4,52,8);
- TextAttr:=attr;
- ch:=ReadKey;
- Exit;
- END;
- Assign(f,Filenamelang);
- Rewrite(f,1);
- BlockWrite(f,PICHeader[1],Length(PICHeader));
-
- {Bilddaten zusammenstellen:}
- FOR i:=0 TO 3 DO New(picture[i]);
- FOR y:=0 TO YMAX DO
- FOR x:=0 TO XMAX SHR 2 DO
- BEGIN
- t:=y*LINESIZE;
- picture[0]^[t+x]:=Workarea.data^[y*WorkArea.SizeX +x shl 2 +0];
- picture[1]^[t+x]:=Workarea.data^[y*WorkArea.SizeX +x shl 2 +1];
- picture[2]^[t+x]:=Workarea.data^[y*WorkArea.SizeX +x shl 2 +2];
- picture[3]^[t+x]:=Workarea.data^[y*WorkArea.SizeX +x shl 2 +3];
- END;
- FOR i:=0 TO 3 DO BlockWrite(f,picture[i]^,PAGESIZE);
- Close(f);
-
- FOR i:=0 TO 3 DO Dispose(picture[i]);
- IF NOT PalEqual(ActualColors,DefaultColors)
- THEN BEGIN
- SaveActualColors;
- attr:=TextAttr; TextColor(White); TextBackground(Blue);
- GotoXY(10,5);
- WRITE(' The actually used colors differ from the ');
- GotoXY(10,6);
- WRITE(' VGA''s default color palette. Therefore, ');
- GotoXY(10,7);
- WRITE(' the palette has been saved to disk, too! ');
- Rahmen(9,4,52,8);
- TextAttr:=attr;
- ch:=ReadKey;
- END;
- END;
-
-
- PROCEDURE SpeichereSprite; {COD's}
- { in: Filenamelang = Name der zu schreibenden Datei}
- { oldName* = alte Dateinamen}
- {out: Falls Sprite nicht erstellt werden konnte, wurden die alten}
- { Dateinamen für Filename* wieder eingesetzt!}
- {rem: Der Inhalt der Workarea wird in die Datei Filenamelang }
- { geschrieben; der Dateiname wurde bereits auf Eröffenbar-}
- { keit geprüft, ebenso, daß die Workarea nicht leer ist! }
- LABEL quit;
- VAR f:File;
- i,j,offset,Plane_Groesse:WORD;
- Gesamtgroesse:LONGINT;
- temp,p:Byte;
- links,rechts,oben,unten:Integer;
- fertig_li,fertig_re,fertig_ob,fertig_un:Boolean;
- Sprite:^spritetyp; {Hier steht das eigentliche Sprite drinnen}
- s:String[20];
- s1,s2:STRING[5];
- pp:POINTER;
- pplen:WORD;
- attr:BYTE;
- ch:CHAR;
- BEGIN
- IF MaxAvail<SizeOf(Sprite^)
- THEN BEGIN
- attr:=TextAttr; TextColor(White); TextBackground(Blue);
- GotoXY(10,5);
- WRITE('Not enough heap memory to complete action!');
- GotoXY(10,6);
- WRITE(' needed memory : ',SizeOf(Sprite^):7,' bytes ');
- GotoXY(10,7);
- WRITE(' available memory: ',MaxAvail:7,' bytes ');
- Rahmen(9,4,52,8);
- TextAttr:=attr;
- ch:=ReadKey;
- Exit
- END;
- New(Sprite);
- FillChar(Sprite^.Readin,SizeOf(Sprite^.Readin),0);
- WITH Sprite^ DO
- BEGIN
- Translate[1]:=1; Translate[2]:=2; Translate[3]:=4; Translate[4]:=8;
- Kennung[1]:='K'; Kennung[2]:='R';
- Version:=1;
- Modus:=0;
- FOR i:=1 TO 10 DO dummy[i]:=0; {Dummywerte auf 0 setzen}
- Hoehe_in_Zeilen:=Succ(WorkArea.MaxUsedY); {Y-Werte reichen von 0..MaxY}
- Breite_in_4er_Gruppen:=Succ(WorkArea.MaxUsedX shr 2); {0..3->1, 4..7->2, ...}
- {Anzahl Bytes pro Plane:}
- Plane_Groesse:=Hoehe_in_Zeilen*Breite_in_4er_Gruppen;
-
- {Indizes für Grenz- & Planedaten:}
- ZeigerL:=Kopf; {Fängt beim 1.Datenbyte an}
- ZeigerR:=ZeigerL+ (Hoehe_in_Zeilen*2);
- ZeigerO:=ZeigerR+ (Hoehe_in_Zeilen*2);
- ZeigerU:=ZeigerO+ (Breite_in_4er_Gruppen*4 *2);
- Zeiger_auf_Plane[0] :=ZeigerU+ (Breite_in_4er_Gruppen*4 *2);
- Zeiger_auf_Plane[1] :=Zeiger_auf_Plane[0]+ Plane_Groesse;
- Zeiger_auf_Plane[2] :=Zeiger_auf_Plane[1]+ Plane_Groesse;
- Zeiger_auf_Plane[3] :=Zeiger_auf_Plane[2]+ Plane_Groesse;
-
- {Das Sprite besteht aus: "Kopf" Bytes an Zeigern & speziellen Infos,}
- {4 Tabellen mit Planedaten, 2 Tabellen mit X-Grenzen (Wörter!), }
- {2 Tabellen mit Y-Grenzen (Wörter, für jeden X-Wert einen!) }
- Gesamtgroesse:=LONGINT(Kopf)+(Plane_Groesse*4)+
- (Hoehe_in_Zeilen*2)*2+
- (Breite_in_4er_Gruppen*4 *2)*2;
-
- IF Gesamtgroesse>SizeOf(SpriteTyp)
- THEN BEGIN
- Str(Gesamtgroesse:5,s1);
- Str(SizeOf(SpriteTyp):5,s2);
- Write(#7);
- OkBox(MeldungX,MeldungY,MeldungX+220,MeldungY+60,'ok',
- 'Sprite would be to big!',
- '(is:'+s1+', max:'+s2+')','',Abfrage);
- Filenamelang:=oldNamelang; Filenamekurz:=oldNamekurz;
- goto quit;
- END;
-
- SpriteLength:=Gesamtgroesse;
-
- {Jetzt die eigentlichen Spritedaten berechnen:}
- offset:=0;
- FOR j:=0 TO WorkArea.MaxUsedY DO
- FOR i:=0 TO Pred(Breite_in_4er_Gruppen) DO
- BEGIN
- FOR p:=0 TO 3 DO
- Readin[Zeiger_auf_Plane[p]+offset]:=
- Workarea.data^[j*WorkArea.SizeX +(i shl 2)+p];
- inc(offset);
- END;
-
- {Nun die X-Grenzdaten für jede Zeile:}
- offset:=0;
- FOR j:=0 TO WorkArea.MaxUsedY DO
- BEGIN
- links:=0;
- rechts:=WorkArea.MaxUsedX;
- fertig_li:=false; fertig_re:=false;
- REPEAT
- if (not fertig_li and (WorkArea.data^[j*WorkArea.SizeX +links]=0))
- THEN inc(links) ELSE fertig_li:=true;
- if (not fertig_re and (WorkArea.data^[j*WorkArea.SizeX +rechts]=0))
- THEN dec(rechts) ELSE fertig_re:=true;
- if links>rechts THEN BEGIN fertig_li:=true; fertig_re:=true END;
- UNTIL fertig_li and fertig_re;
- if links>rechts
- THEN BEGIN {Leerzeile, Sentinelwerte eintragen}
- readin[ZeigerL+offset]:=lo(+16000);
- readin[Succ(ZeigerL+offset)]:=hi(+16000);
- readin[ZeigerR+offset]:=lo(-16000);
- readin[Succ(ZeigerR+offset)]:=hi(-16000)
- END
- ELSE BEGIN {normale Zeile, Grenzen eintragen}
- readin[ZeigerL+offset]:=lo(links);
- readin[Succ(ZeigerL+offset)]:=hi(links);
- readin[ZeigerR+offset]:=lo(rechts);
- readin[Succ(ZeigerR+offset)]:=hi(rechts)
- END;
- inc(offset,2) {Grenzeinträge sind Wörter!}
- END;
-
- {Dasselbe für die Grenzdaten jeder Spalte:}
- offset:=0;
- FOR i:=0 TO Pred(Breite_in_4er_Gruppen shl 2) DO
- BEGIN
- oben :=0;
- unten:=WorkArea.MaxUsedY;
- fertig_ob:=false; fertig_un:=false;
- REPEAT
- if (not fertig_ob and (Workarea.data^[oben*WorkArea.SizeX +i]=0))
- THEN inc(oben) ELSE fertig_ob:=true;
- if (not fertig_un and (Workarea.data^[unten*WorkArea.SizeX +i]=0))
- THEN dec(unten) ELSE fertig_un:=true;
- if oben>unten THEN BEGIN fertig_ob:=true; fertig_un:=true END;
- UNTIL fertig_ob and fertig_un;
- if oben>unten
- THEN BEGIN {Leerspalte, Sentinelwerte eintragen}
- readin[ZeigerO+offset]:=lo(+16000);
- readin[Succ(ZeigerO+offset)]:=hi(+16000);
- readin[ZeigerU+offset]:=lo(-16000);
- readin[Succ(ZeigerU+offset)]:=hi(-16000)
- END
- ELSE BEGIN {normale Spalte, Grenzen eintragen}
- readin[ZeigerO+offset]:=lo(oben);
- readin[Succ(ZeigerO+offset)]:=hi(oben);
- readin[ZeigerU+offset]:=lo(unten);
- readin[Succ(ZeigerU+offset)]:=hi(unten)
- END;
- inc(offset,2) {Grenzeinträge sind Wörter!}
- END;
-
- END; {of with}
-
- {Nun die Daten auf Disk schreiben:}
- Assign(f,Filenamelang);
- Rewrite(f,1);
- BlockWrite(f,sprite^.readin,Gesamtgroesse);
- Close(f);
- IF NOT PalEqual(ActualColors,DefaultColors)
- THEN BEGIN
- SaveActualColors;
- attr:=TextAttr; TextColor(White); TextBackground(Blue);
- GotoXY(10,5);
- WRITE(' The actually used colors differ from the ');
- GotoXY(10,6);
- WRITE(' VGA''s default color palette. Therefore, ');
- GotoXY(10,7);
- WRITE(' the palette has been saved to disk, too! ');
- Rahmen(9,4,52,8);
- TextAttr:=attr;
- ch:=ReadKey;
- END;
-
- quit:;
- Dispose(Sprite);
- END;
-
- FUNCTION gueltig(VAR P:InputString; Ext:ExtStr):Boolean;
- { in: P = vollständiger Dateiname}
- { Ext = gewünschte Defaultextension, falls P selber keine hat}
- {out: TRUE/FALSE, wenn unter dem angegebenen Namen eine Datei angelegt}
- { werden kann und deren Endung "Ext" ist}
- { P = vollständiger Dateiname, um "Ext" erweitert, wenn keine Ex- }
- { tension angegeben wurde, evtl. Leerzeichen wurden entfernt }
- {rem: Eine schon bestehende Datei gleichen Namens wird überschrieben! }
- { P muß in Großschrift sein!}
- VAR i:Byte;
- D: DirStr;
- N: NameStr;
- E: ExtStr;
-
- FUNCTION eroeffenbar(P:PathStr):Boolean;
- VAR f:File;
- temp:Boolean;
- BEGIN
- assign(f,P);
- {$I-}
- rewrite(f);
- {$I+}
- temp:=ioresult=0;
- if temp THEN close(f);
- eroeffenbar:=temp
- END;
-
- BEGIN
- WHILE (P[1]=' ') DO delete(P,1,1);
- WHILE (P[Length(P)]=' ') DO delete(P,Length(P),1);
- IF POS(' ',P)>0
- THEN BEGIN
- gueltig:=FALSE;
- exit
- END;
-
- FSplit(P, D, N, E);
- IF E='' THEN E:=Ext;
- P := D + N + E;
-
- if (n='') {Kein Namen angegeben?}
- or (pos('*',p)>0) {keine Wildcards erlaubt}
- or (pos('?',p)>0)
- or (pos(':',N+E)>0) {LW-Angaben sind nur im Pfad erlaubt}
- or (E<>Ext) {nur "Ext" als Endung erlaubt}
- or ( (pos(':',D)>0) and (pos(':',D)<>2) ) {":" muß an 2.Position sein}
- or (not eroeffenbar(P))
- THEN BEGIN gueltig:=false; exit END
- ELSE gueltig:=true
- END;
-
- PROCEDURE Speichern;
- VAR Breite_in_4er_Gruppen:WORD;
- Plane_Groesse,Gesamtgroesse:LONGINT;
- s1,s2:STRING[10];
- x,y:WORD;
- c:BYTE;
-
- name:TPath;
- error:BOOLEAN;
- oldInt24h:POINTER;
-
- FUNCTION HoleFileNamen(Ext:ExtStr):BOOLEAN;
- { in: Ext = erwartete Extension (COD oder PIC)}
- CONST x1=4; y1=4; inlen=67; {Koordinaten für Eingabebox}
- VAR temp:InputString;
- abbruch:Boolean;
- size:word;
- attr:Byte;
- i:Integer;
- ch:Char;
- oldNamelang,oldNamekurz,
- P: PathStr;
- D: DirStr;
- N: NameStr;
- E: ExtStr;
- BEGIN
- {evtl. alten Filenamen aufheben}
- oldNamelang:=Filenamelang; oldNamekurz:=Filenamekurz;
-
- ClrScr;
-
- GotoXY(x1,y1-2);
- WRITE('Please give a name (*.'+Ext+') for your sprite file; <ESC> to cancel');
- GotoXY(1,y1+6);
- WRITELN('Use the following keys to edit your input:'); WRITELN;
- WRITELN('HOME/END : move cursor to the start/end of line');
- WRITELN('LEFT/RIGHT : move cursor one char');
- WRITELN('^LEFT/^RIGHT, ^A/^F : move cursor one word');
- WRITELN;
- WRITELN('INS, ^V : toggle insert/overwrite mode');
- WRITELN('UP/DOWN, ^E/^X : review the last (up to 30) input lines');
- WRITELN;
- WRITELN('^T : delete word DEL, ^G : delete char under cursor');
- WRITELN('^K : delete to end of line BSPC,^H : backspace');
- WRITELN('^Y : delete whole input line ESC : cancel input');
-
- attr:=textattr; textattr:=ChoseColor;
-
- {Defaultwert für Namen aus Filenamelang bestimmen:}
- IF Filenamelang<>''
- THEN BEGIN {dafür sorgen, daß evtl. Extension = Ext ist}
- FSplit(Filenamelang,D,N,E);
- temp:=D+N+'.'+Ext
- END
- ELSE temp:='';
-
- abbruch:=false; {heißt: behalte die letzten gemachten Eingaben}
- GotoXY(x1,y1+1); {= 1.Position in der Eingabetextbox}
- BoxGetString(temp,inlen,abbruch,'enter filename:');
- textattr:=attr;
- IF abbruch
- THEN BEGIN {ESC gedrückt}
- Window(1,y1+3,80,25); ClrScr; Window(1,1,80,25);
- GotoXY(x1,y1+4);
- WRITE('You didn''t choose a file! <any key>');
- ch:=readkey; while keypressed do ch:=readkey;
- END
- ELSE BEGIN {Dateinamen ausprobieren}
- FOR i:=1 TO Length(temp) DO
- CASE temp[i] OF
- 'ä':temp[i]:='Ä';
- 'ö':temp[i]:='Ö';
- 'ü':temp[i]:='Ü'
- ELSE temp[i]:=upcase(temp[i])
- END;
-
- if not gueltig(temp,'.'+Ext)
- THEN BEGIN {ungültiger Dateiname}
- Window(1,y1+3,80,25); ClrScr; Window(1,1,80,25);
- GotoXY(x1,y1+4);
- ClrEol; WRITELN('*** Error! Couldn''t open file with name:');
- ClrEol; WRITELN;
- ClrEol; WRITELN(temp);
- ClrEol; WRITELN;
- ClrEol; WRITE('(invalid access path or filename)! <any key>');
- ch:=readkey; while keypressed do ch:=readkey;
- abbruch:=true; {Ist auch als Abbruch zu bewerten!}
- END
- ELSE BEGIN {gültiger Name, in Filename_* übernehmen}
- P:=temp;
- FSplit(P,D,N,E);
- Filenamelang:=P;
- Filenamekurz:=N+E;
- END;
- END;
- HoleFileNamen:=NOT abbruch;
- END;
-
- BEGIN
- WITH oldMouse DO
- BEGIN
- IF (breite=320) AND (hoehe=200)
- THEN BEGIN
- IF breite*hoehe>MaxAvail
- THEN BEGIN
- Str(breite*hoehe:7,s1);
- Str(MaxAvail:7,s2);
- OkBox((GetMaxX-200) SHR 1,MeldungY,(GetMaxX-200) SHR 1+200,MeldungY+60,'ok',
- 'Not enough heap memory:',
- 'needed: '+s1,
- 'max : '+s2,Abfrage);
- exit;
- END
- ELSE BEGIN
- {nun loslegen: Speicher reservieren und Grafik auslesen}
- GetMem(WorkArea.data,breite*hoehe);
- WorkArea.SizeX:=breite;
- WorkArea.SizeY:=hoehe;
- WorkArea.MaxUsedX:=-1;
- WorkArea.MaxUsedY:=-1;
- FOR y:=0 TO hoehe-1 DO
- BEGIN
- FOR x:=0 TO breite-1 DO
- BEGIN
- c:=GetPixel(x+oldX,y+oldY);
- WorkArea.data^[y*breite+x]:=c;
- IF c<>0
- THEN BEGIN
- WorkArea.MaxUsedY:=y;
- IF x>WorkArea.MaxUsedX
- THEN WorkArea.MaxUsedX:=x
- END;
- END;
- END;
-
- IF (WorkArea.MaxUsedX=0) AND (WorkArea.MaxUsedY=0) AND
- (WorkArea.data^[0]=transparent)
- THEN BEGIN {Workarea leer!}
- ErrBeep;
- OkBox((GetMaxX-200) SHR 1,MeldungY,
- (GetMaxX-200) SHR 1+200,MeldungY+60,'ok',
- 'Workarea is empty;',
- 'nothing to do!',
- '',Abfrage);
- exit
- END;
-
-
- GetBigPalette(actualColors); {aktuelle Farbpalette merken}
-
- RestoreCRTmode;
-
- IF HoleFileNamen('PIC')
- THEN BEGIN
- SpeichereHintergrund; {Eigentliche Daten berechnen & schreiben}
- END;
- FreeMem(WorkArea.data,breite*hoehe);
-
- SetGraphMode(GetGraphMode);
- DisplayPCXagain;
- END; {of ELSE breite*hoehe<=MaxAvail}
-
- END {of IF (breite=320) AND (hoehe=200) }
- ELSE BEGIN
- Breite_in_4er_Gruppen:=Succ((breite-1) shr 2); {0..3->1, 4..7->2, ...}
- {Anzahl Bytes pro Plane:}
- Plane_Groesse:=LONGINT(hoehe)*Breite_in_4er_Gruppen;
- Gesamtgroesse:=LONGINT(Kopf)+(Plane_Groesse*4)+
- (hoehe*2)*2+
- (Breite_in_4er_Gruppen*4 *2)*2;
-
- IF Gesamtgroesse>SizeOf(SpriteTyp)
- THEN BEGIN
- Str(Gesamtgroesse:7,s1);
- Str(SizeOf(SpriteTyp):7,s2);
- OkBox((GetMaxX-200) SHR 1,MeldungY,(GetMaxX-200) SHR 1+200,MeldungY+60,'ok',
- 'Sprite would be to big:',
- 'needed: '+s1,
- 'max : '+s2,Abfrage);
- exit;
- END;
-
- IF breite*hoehe>SizeOf(WorkAreaTyp)
- THEN BEGIN
- Str(breite*hoehe:7,s1);
- Str(SizeOf(WorkAreaTyp):7,s2);
- OkBox((GetMaxX-200) SHR 1,MeldungY,(GetMaxX-200) SHR 1+200,MeldungY+60,'ok',
- 'Sprite would be to big:',
- 'needed: '+s1,
- 'max : '+s2,Abfrage);
- exit;
- END;
-
- IF breite*hoehe>MaxAvail
- THEN BEGIN
- Str(breite*hoehe:7,s1);
- Str(MaxAvail:7,s2);
- OkBox((GetMaxX-200) SHR 1,MeldungY,(GetMaxX-200) SHR 1+200,MeldungY+60,'ok',
- 'Not enough heap memory:',
- 'needed: '+s1,
- 'max : '+s2,Abfrage);
- exit;
- END;
-
- {nun loslegen: Speicher reservieren und Grafik auslesen}
- GetMem(WorkArea.data,breite*hoehe);
- WorkArea.SizeX:=breite;
- WorkArea.SizeY:=hoehe;
- WorkArea.MaxUsedX:=-1;
- WorkArea.MaxUsedY:=-1;
- FOR y:=0 TO hoehe-1 DO
- BEGIN
- FOR x:=0 TO breite-1 DO
- BEGIN
- c:=GetPixel(x+oldX,y+oldY);
- WorkArea.data^[y*breite+x]:=c;
- IF c<>0
- THEN BEGIN
- WorkArea.MaxUsedY:=y;
- IF x>WorkArea.MaxUsedX
- THEN WorkArea.MaxUsedX:=x
- END;
- END;
- END;
-
- IF (WorkArea.MaxUsedX=0) AND (WorkArea.MaxUsedY=0) AND
- (WorkArea.data^[0]=transparent)
- THEN BEGIN {Workarea leer!}
- ErrBeep;
- OkBox((GetMaxX-200) SHR 1,MeldungY,(GetMaxX-200) SHR 1+200,MeldungY+60,'ok',
- 'Workarea is empty;',
- 'nothing to do!',
- '',Abfrage);
- exit
- END;
-
-
- GetBigPalette(actualColors); {aktuelle Farbpalette merken}
-
- RestoreCRTmode;
-
- IF HoleFileNamen('COD')
- THEN BEGIN
- SpeichereSprite; {Eigentliche Daten berechnen & schreiben}
- END;
- FreeMem(WorkArea.data,breite*hoehe);
-
- SetGraphMode(GetGraphMode);
- DisplayPCXagain;
- END;
- END;
- END;
-
- {------------------- PCX-Routinen --------------------}
-
- CONST MaxLineWidth=1023; {max. X-Koord. einer Zeile}
- ErrWrongPCXVersion=1;
- BufSize=2048; {E/A-Puffergröße für schnelleren Filezugriff}
-
- VAR OnePCXline:ARRAY[0..3,0..MaxLineWidth] OF BYTE;
- type TPCXHeader=Record
- Manufacturer,Version,Encoding,BitsPerPixel:BYTE;
- xmin,ymin,xmax,ymax,hres,vres:INTEGER;
- palette:ARRAY[0..15,0..2] OF BYTE;
- Reserved,NPlanes:BYTE;
- BytesPerLine,paletteinfo:INTEGER;
- Filler:ARRAY[0..57] OF BYTE;
- END;
- CONST RLEbyte :BYTE=0; {Anfangswerte so wählen, daß beim ersten }
- ReadByte:BYTE=0; {Zugriff ein Block von der Diskette einge-}
- Index:WORD=BufSize; {lesen werden wird!}
- FileDone:BOOLEAN=FALSE;
- VAR Buffer:ARRAY[1..BufSize] OF BYTE;
- Header:TPCXHeader;
- PCXname:PathStr;
- MaxZeile:INTEGER;
- AnzColors:LONGINT;
- fin:FILE;
- Tag:BYTE;
- Pal256:ARRAY[0..255,0..2] OF BYTE;
- p:POINTER;
-
- PROCEDURE ErrorMsg(s:STRING);
- BEGIN
- WRITELN('Error: ',s);
- Halt
- END;
-
- FUNCTION GetByte(VAR fin:file):BYTE;
- VAR n:BYTE;
-
- PROCEDURE GetNextBlock;
- VAR temp:WORD;
- BEGIN
- IF NOT EOF(fin)
- THEN BEGIN
- blockread(fin,Buffer,BufSize,temp);
- Index:=1
- END
- ELSE FileDone:=true;
- END;
-
- FUNCTION GetCh:BYTE;
- BEGIN
- IF NOT FileDone
- THEN BEGIN
- IF Index=BufSize
- THEN GetNextBlock
- ELSE Inc(Index);
- GetCh:=Buffer[Index]
- END
- ELSE GetCh:=0;
- END;
-
- BEGIN
- IF RLEbyte>0
- THEN BEGIN
- GetByte:=ReadByte;
- Dec(RLEbyte);
- exit
- END;
- n:=GetCh;
- IF n AND $C0 = $C0
- THEN BEGIN {Run Length Encoded}
- ReadByte:=GetCh;
- RLEbyte:=n AND $3f -1
- END
- ELSE BEGIN {normales Databyte}
- ReadByte:=n;
- RLEbyte:=0
- END;
- GetByte:=ReadByte
- END;
-
- PROCEDURE ReadPCXHeader(name:PathStr; VAR Header:TPCXHeader; VAR fin:FILE);
- { in: name = Name der PCX-Datei}
- {out: Header = erste 128 Bytes der PCX-Datei}
- { fin = zum lesen geöffnete PCX-Datei}
- VAR temp:INTEGER;
- BEGIN
- {$I-}
- Assign(fin,name); Reset(fin,1); blockread(fin,Header,128);
- {$I+}
- Error:=IOResult;
- IF Error<>0
- THEN BEGIN
- {$I-} Close(fin); {$I+}
- temp:=IOResult;
- exit
- END;
- If (Header.version>5) or (Header.encoding>1)
- THEN Error:=ErrWrongPCXVersion;
- END;
-
- PROCEDURE DisplayPCXdata(VAR Header:TPCXHeader; MaxZeile:INTEGER;
- VAR fin:FILE);
- { in: Header = erste 128 Bytes der PCX-Datei}
- { MaxZeile = letzte auszulesende Zeile aus der PCX-Datei}
- { fin = zum lesen geöffnete PCX-Datei}
- {out: fin = geschlossene Datei}
- {rem: PCX-File wurde auf dem Schirm dargestellt; Grafikmodus & Palette}
- { müssen bereits gesetzt sein}
- LABEL break1;
- CONST Einsen:ARRAY[1..8] OF BYTE=(1,3,7,15,31,63,127,255);
- VAR i,j,k,l,x,px:INTEGER;
- p:POINTER;
- steps,Maske,cutoff:BYTE;
- c:LONGINT;
- BEGIN
- {$I-} Seek(fin,128); {$I+}
- IF IOResult<>0 THEN exit;
- FOR l:=0 TO MaxZeile DO
- BEGIN
- FOR j:=0 TO Header.NPlanes-1 DO
- BEGIN
- FOR i:=0 TO Header.BytesPerLine-1 DO
- OnePCXline[j,i]:=GetByte(fin) {*ganze* Zeile aus Datei holen}
- END;
-
- steps:=(8 DIV Header.BitsPerPixel); {Anzahl Pixel pro Byte}
- Maske:=Einsen[Header.BitsPerPixel]; {Maske zur Isolierung eines Punktes}
- FOR x:=0 TO Header.BytesPerLine-1 DO
- BEGIN
- FOR j:=steps-1 DOWNTO 0 DO
- BEGIN
- {berechne c:=Bits der höchsten Plane||Bits der nächsten Plane||etc}
- {Beispiel: normales 16 Farbenbild (4 Planes, 1 Bit je Plane):}
- {c:=1Bit von Plane3||1Bit von Plane2||1Bit von Plane1||1Bit von Plane0}
- {Beispiel: 24Bit-Farbbild (3 Planes, 8 Bit je Plane):}
- {c:=8Bit von Plane2||8Bit von Plane1||8Bit von Plane0}
- c:=0;
- cutoff:=j*Header.BitsPerPixel; {zur Ausmaskierung der relavanten Bits}
- FOR k:=Header.NPlanes-1 DOWNTO 0 DO
- c:=(c SHL Header.BitsPerPixel)+((OnePCXline[k,x] SHR cutoff) AND Maske);
- px:=x*Steps+Pred(steps-j)*Header.BitsPerPixel;
- IF px>GetMaxX THEN goto break1; {Bild ist horizontal zu groß}
- PutPixel(px,l,c);
- END;
- END;
- break1:;
-
- END; {of FOR l}
-
- Close(fin);
- END;
-
- PROCEDURE DisplayPCXagain;
- BEGIN
- RLEbyte :=0;
- ReadByte:=0;
- Index:=BufSize;
- FileDone:=FALSE;
- IF AnzColors=256
- THEN BEGIN {Farbpalette steht am Ende der Datei}
- FOR i:=0 TO AnzColors-1 DO
- BEGIN
- ActualColors[i].red :=Pal256[i][0] SHR 2;
- ActualColors[i].green:=Pal256[i][1] SHR 2;
- ActualColors[i].blue :=Pal256[i][2] SHR 2;
- END;
- SetPalette(ActualColors);
- END
- ELSE IF AnzColors<=16
- THEN FOR i:=0 TO AnzColors-1 DO
- SetRGBPalette(i,Header.Palette[i][0] SHR 2,
- Header.Palette[i][1] SHR 2,
- Header.Palette[i][2] SHR 2);
- GetBigPalette(ActualColors);
- Assign(fin,PCXname); Reset(fin,1);
- DisplayPCXdata(Header,MaxZeile,fin);
- END;
-
- {------------------- Hauptprogramm -------------------}
-
- BEGIN
- IF ParamCount<>1
- THEN BEGIN
- WRITELN;
- WRITELN('PCX2COD converter, V0.9ß --by Kai Rohrbacher (c) 1993');
- WRITELN('Converts PCX-files into *.COD or *.PIC files.');
- WRITELN;
- WRITELN('Call PCX2COD in the following way:');
- WRITELN;
- WRITELN(ParamStr(0)+' pcxfile.pcx');
- WRITELN;
- WRITELN('Use the mouse and the left button to select the part of'+
- ' the picture');
- WRITELN('you want to convert, then press <Return> to save it.');
- Halt
- END;
- PCXname:=ParamStr(1);
-
- IF InstallUserDriver('SVGA256',@DetectVGA256)<0 {RegisterBGIDriver geht leider nicht!}
- THEN ErrorMsg('Graphic error: '+GraphErrorMsg(GraphResult));
-
- ReadPCXHeader(PCXname,Header,fin);
- IF Error<>0
- THEN ErrorMsg('Couldn''t find file '+PCXname);
- AnzColors:=1 SHL (Header.BitsPerPixel*Header.NPlanes);
- IF AnzColors=256
- THEN BEGIN {Farbpalette steht am Ende der Datei}
- Seek(fin,FileSize(fin)-769);
- BlockRead(fin,Tag,1);
- IF Tag<>$0C
- THEN BEGIN
- Close(fin);
- ErrorMsg('No true 256-color-PCX!');
- END
- ELSE BEGIN
- BlockRead(fin,Pal256,SizeOf(Pal256));
- END
- END;
-
- Init;
-
- {Farbpaletten: im PCX sind die RGB-Werte immer 8 Bit breit; der }
- {256-Farbenmodus verwendet aber nur 6 Bit, deshalb wird um 2 Bit}
- {rechts verschoben!}
- IF AnzColors=256
- THEN BEGIN {Farbpalette steht am Ende der Datei}
- FOR i:=0 TO AnzColors-1 DO
- BEGIN
- ActualColors[i].red :=Pal256[i][0] SHR 2;
- ActualColors[i].green:=Pal256[i][1] SHR 2;
- ActualColors[i].blue :=Pal256[i][2] SHR 2;
- END;
- SetPalette(ActualColors);
- END
- ELSE IF AnzColors<=16
- THEN FOR i:=0 TO AnzColors-1 DO
- SetRGBPalette(i,Header.Palette[i][0] SHR 2,
- Header.Palette[i][1] SHR 2,
- Header.Palette[i][2] SHR 2);
-
- GetBigPalette(ActualColors);
-
- MaxZeile:=Header.ymax-Header.ymin;
- IF MaxZeile>GetMaxY
- THEN MaxZeile:=GetMaxY;
- DisplayPCXdata(Header,MaxZeile,fin);
-
- DrawMaus; {...und anzeigen}
- EnableMouse;
-
- repeat
- IF KeyPressed
- THEN BEGIN
- ch:=ReadKey; Shift:=(mem[$0:$417] AND 3)<>0;
- IF ch=#0
- THEN Wahl:=ORD(ReadKey) SHL 8 {Funktionstasten -> >256}
- ELSE Wahl:=ORD(ch);
- CASE Wahl OF
- $3B00: Event:=EventHelp; {F1 = Hilfe}
- 13: Event:=EventSpeichern; {CR = File speichern}
- $1B,$4400: Event:=EventQuit; {ESC,F10 = Beenden}
- else Event:=EventError;
- END;
- END;
-
- IF Event=EventNone {keine Taste gedrückt, aber vielleicht Mausaktion?}
- THEN IF MouseUpdate
- THEN BEGIN {Mausaktion}
- {N.B.: soll ein Event jetzt noch nachträglich "gelöscht" }
- {werden, so muß es auf "EventMouseMoved" gesetzt werden, }
- {nicht aber auf "EventNone", denn es ist ja was mit der }
- {Maus passiert, (sie wurde zumindest bewegt oder geclickt)}
- {Würde man dies ignorieren, so würde die Maus nicht mehr }
- {"enabled" werden!}
- Event:=MouseEvent(menu);
- END;
-
- IF Event<>EventNone
- THEN UnDrawMaus; {alten Bildschirminhalt unter Mauscursor restaurieren}
-
- CASE Event OF
- EventHelp : Help;
- EventSpeichern : Speichern;
- EventNone:;
- EventError : ErrBeep;
- EventMouseMoved : UpdateBox;
- EventQuit : BEGIN {Bei "Quit" lieber nochmal rückfragen}
- IF FirstOfTwoBoxes(MeldungX,MeldungY,
- MeldungX+220,MeldungY+60,
- 'yes','no',
- '','Really quit?','',
- alternative)
- THEN Event:=EventEndProgram
- ELSE Event:=EventMouseMoved
- END
-
- else ErrBeep;
- END;
-
- IF Event<>EventNone
- THEN BEGIN {Mauszeiger wurde gelöscht, jetzt wieder neuzeichnen}
- DrawMaus;
- ClearMouse; {Mausereignis abgearbeitet}
- END;
-
- IF Event<>EventEndProgram THEN Event:=EventNone;
- until Event=EventEndProgram; {Ende = F10 + Bestätigung}
-
- restorecrtmode;
- SwapVectors;
-
- regs.ax := 12;
- regs.cx := 0;
- intr($33,regs); {Mousecallback de-installieren}
-
-
- END.
-